blob: 1f3253f4222e92adb65c9ea1926822ac9f3a98bf [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +01002/*
3 * Copyright (c) 2016 Toradex, Inc.
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +01004 */
5
Emanuele Ghidoli26b5cba2024-02-23 10:11:41 +01006#include <dm.h>
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +01007#include <common.h>
Simon Glass5e6201b2019-08-01 09:46:51 -06008#include <env.h>
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +01009#include <g_dnl.h>
Simon Glass97589732020-05-10 11:40:02 -060010#include <init.h>
Masahiro Yamada75f82d02018-03-05 01:20:11 +090011#include <linux/libfdt.h>
Emanuele Ghidoli26b5cba2024-02-23 10:11:41 +010012#include <sysinfo.h>
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +010013
Simon Glass52cb5042022-10-18 07:46:31 -060014#ifdef CONFIG_VIDEO
Igor Opaniuk897822d2020-07-15 13:31:01 +030015#include <bmp_logo.h>
Igor Opaniuk897822d2020-07-15 13:31:01 +030016#include <splash.h>
17#include <video.h>
18#endif
19
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +010020#include "tdx-cfg-block.h"
Simon Glassd9a766f2017-05-17 08:23:00 -060021#include <asm/setup.h>
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +010022#include "tdx-common.h"
23
Philippe Schenker1832bd32022-06-13 19:35:22 +020024#define SERIAL_STR_LEN 8
25#define MODULE_VER_STR_LEN 4 // V1.1
Philippe Schenker498f95a2022-06-13 19:35:23 +020026#define MODULE_REV_STR_LEN 3 // [A-Z] or #[26-99]
Philippe Schenker1832bd32022-06-13 19:35:22 +020027
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +010028#ifdef CONFIG_TDX_CFG_BLOCK
Philippe Schenker1832bd32022-06-13 19:35:22 +020029static char tdx_serial_str[SERIAL_STR_LEN + 1];
30static char tdx_board_rev_str[MODULE_VER_STR_LEN + MODULE_REV_STR_LEN + 1];
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +010031
Igor Opaniukecfe0f52020-07-15 13:30:57 +030032#ifdef CONFIG_TDX_CFG_BLOCK_EXTRA
Philippe Schenker1832bd32022-06-13 19:35:22 +020033static char tdx_car_serial_str[SERIAL_STR_LEN + 1];
34static char tdx_car_rev_str[MODULE_VER_STR_LEN + MODULE_REV_STR_LEN + 1];
Max Krummenacher2ded2d62023-07-18 11:07:33 +020035static const char *tdx_carrier_board_name;
Igor Opaniukecfe0f52020-07-15 13:30:57 +030036#endif
37
Tom Rini4cc38852021-08-30 09:16:30 -040038#if defined(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)
39u32 get_board_revision(void)
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +010040{
41 /* Check validity */
42 if (!tdx_hw_tag.ver_major)
43 return 0;
44
45 return ((tdx_hw_tag.ver_major & 0xff) << 8) |
46 ((tdx_hw_tag.ver_minor & 0xf) << 4) |
47 ((tdx_hw_tag.ver_assembly & 0xf) + 0xa);
48}
49#endif /* CONFIG_TDX_CFG_BLOCK */
50
51#ifdef CONFIG_SERIAL_TAG
52void get_board_serial(struct tag_serialnr *serialnr)
53{
54 int array[8];
55 unsigned int serial = tdx_serial;
56 int i;
57
58 serialnr->low = 0;
59 serialnr->high = 0;
60
61 /* Check validity */
62 if (serial) {
63 /*
64 * Convert to Linux serial number format (hexadecimal coded
65 * decimal)
66 */
67 i = 7;
68 while (serial) {
69 array[i--] = serial % 10;
70 serial /= 10;
71 }
72 while (i >= 0)
73 array[i--] = 0;
74 serial = array[0];
75 for (i = 1; i < 8; i++) {
76 serial *= 16;
77 serial += array[i];
78 }
79
80 serialnr->low = serial;
81 }
82}
83#endif /* CONFIG_SERIAL_TAG */
84
Philippe Schenker498f95a2022-06-13 19:35:23 +020085static const char *get_board_assembly(u16 ver_assembly)
86{
87 static char ver_name[MODULE_REV_STR_LEN + 1];
88
89 if (ver_assembly < 26) {
90 ver_name[0] = (char)ver_assembly + 'A';
91 ver_name[1] = '\0';
92 } else {
93 snprintf(ver_name, sizeof(ver_name),
94 "#%u", ver_assembly);
95 }
96
97 return ver_name;
98}
99
Emanuele Ghidoli1e9459e2024-02-23 10:11:38 +0100100__weak int print_bootinfo(void)
101{
102 return 0;
103}
104
105int checkboard(void)
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100106{
Emanuele Ghidoli26b5cba2024-02-23 10:11:41 +0100107 if (valid_cfgblock)
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100108 printf("Serial#: %s\n", tdx_serial_str);
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100109
110#ifdef CONFIG_TDX_CFG_BLOCK_EXTRA
111 if (tdx_carrier_board_name)
112 printf("Carrier: Toradex %s %s, Serial# %s\n",
113 tdx_carrier_board_name,
114 tdx_car_rev_str,
115 tdx_car_serial_str);
116#endif
117
118 print_bootinfo();
119
120 return 0;
121}
122
123static int settings_r(void)
124{
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100125 unsigned char ethaddr[6];
126
127 if (read_tdx_cfg_block()) {
Bhuvanchandra DV2190ade2019-03-25 17:18:28 +0100128 printf("MISSING TORADEX CONFIG BLOCK\n");
Philippe Schenkerd52a2572022-06-20 16:57:45 +0200129 get_mac_from_serial(tdx_serial, &tdx_eth_addr);
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100130
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100131 /* Board can run even if config block is not present */
132 return 0;
133 }
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100134
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100135 snprintf(tdx_serial_str, sizeof(tdx_serial_str),
136 "%08u", tdx_serial);
137 snprintf(tdx_board_rev_str, sizeof(tdx_board_rev_str),
138 "V%1d.%1d%s",
139 tdx_hw_tag.ver_major,
140 tdx_hw_tag.ver_minor,
141 get_board_assembly(tdx_hw_tag.ver_assembly));
142
143 env_set("serial#", tdx_serial_str);
144
Igor Opaniukecfe0f52020-07-15 13:30:57 +0300145#ifdef CONFIG_TDX_CFG_BLOCK_EXTRA
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100146 if (read_tdx_cfg_block_carrier()) {
147 printf("MISSING TORADEX CARRIER CONFIG BLOCKS\n");
148 try_migrate_tdx_cfg_block_carrier();
149 } else {
150 tdx_carrier_board_name =
151 get_toradex_carrier_boards(tdx_car_hw_tag.prodid);
Igor Opaniukecfe0f52020-07-15 13:30:57 +0300152
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100153 snprintf(tdx_car_serial_str, sizeof(tdx_car_serial_str),
154 "%08u", tdx_car_serial);
155 snprintf(tdx_car_rev_str, sizeof(tdx_car_rev_str),
156 "V%1d.%1d%s",
157 tdx_car_hw_tag.ver_major,
158 tdx_car_hw_tag.ver_minor,
159 get_board_assembly(tdx_car_hw_tag.ver_assembly));
Igor Opaniukecfe0f52020-07-15 13:30:57 +0300160
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100161 env_set("carrier_serial#", tdx_car_serial_str);
Bhuvanchandra DV2190ade2019-03-25 17:18:28 +0100162 }
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100163#endif
Emanuele Ghidoli1e9459e2024-02-23 10:11:38 +0100164
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100165 /*
166 * Check if environment contains a valid MAC address,
167 * set the one from config block if not
168 */
Simon Glass399a9ce2017-08-03 12:22:14 -0600169 if (!eth_env_get_enetaddr("ethaddr", ethaddr))
Simon Glass8551d552017-08-03 12:22:11 -0600170 eth_env_set_enetaddr("ethaddr", (u8 *)&tdx_eth_addr);
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100171
Francesco Dolcini14163d62022-07-21 15:17:36 +0200172 if (IS_ENABLED(CONFIG_TDX_CFG_BLOCK_2ND_ETHADDR) &&
173 !eth_env_get_enetaddr("eth1addr", ethaddr)) {
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100174 /*
175 * Secondary MAC address is allocated from block
176 * 0x100000 higher then the first MAC address
177 */
178 memcpy(ethaddr, &tdx_eth_addr, 6);
179 ethaddr[3] += 0x10;
Simon Glass8551d552017-08-03 12:22:11 -0600180 eth_env_set_enetaddr("eth1addr", ethaddr);
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100181 }
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100182
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100183 return 0;
184}
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100185EVENT_SPY_SIMPLE(EVT_SETTINGS_R, settings_r);
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100186
Emanuele Ghidoli26b5cba2024-02-23 10:11:41 +0100187static int tdx_detect(struct udevice *dev)
188{
189 return valid_cfgblock ? 0 : -EINVAL;
190}
191
192static int tdx_get_str(struct udevice *dev, int id, size_t size, char *val)
193{
194 int ret = -ENOTSUPP;
195
196 switch (id) {
197 case SYSINFO_ID_BOARD_MODEL:
198 snprintf(val, size,
199 "Toradex %04d %s %s",
200 tdx_hw_tag.prodid,
201 toradex_modules[tdx_hw_tag.prodid].name,
202 tdx_board_rev_str);
203
204 ret = 0;
205 }
206
207 return ret;
208}
209
210static const struct udevice_id sysinfo_tdx_ids[] = {
211 { .compatible = "toradex,sysinfo" },
212 { /* sentinel */ }
213};
214
215static const struct sysinfo_ops sysinfo_tdx_ops = {
216 .detect = tdx_detect,
217 .get_str = tdx_get_str,
218};
219
220U_BOOT_DRIVER(sysinfo_toradex) = {
221 .name = "sysinfo_toradex",
222 .id = UCLASS_SYSINFO,
223 .of_match = sysinfo_tdx_ids,
224 .ops = &sysinfo_tdx_ops,
225};
226
Stefan Agner57985bd2021-07-23 09:39:46 +0300227#ifdef CONFIG_TDX_CFG_BLOCK_USB_GADGET_PID
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100228int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
229{
230 unsigned short usb_pid;
231
232 usb_pid = TORADEX_USB_PRODUCT_NUM_OFFSET + tdx_hw_tag.prodid;
233 put_unaligned(usb_pid, &dev->idProduct);
234
235 return 0;
236}
Stefan Agnera1886522016-11-30 13:41:52 -0800237#endif
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100238
Stefan Agner98ffd0f2016-11-30 13:41:53 -0800239#if defined(CONFIG_OF_LIBFDT)
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +0900240int ft_common_board_setup(void *blob, struct bd_info *bd)
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100241{
242 if (tdx_serial) {
243 fdt_setprop(blob, 0, "serial-number", tdx_serial_str,
244 strlen(tdx_serial_str) + 1);
245 }
246
247 if (tdx_hw_tag.ver_major) {
248 char prod_id[5];
249
Philippe Schenker38cf79e2022-06-13 19:35:21 +0200250 snprintf(prod_id, sizeof(prod_id), "%04u", tdx_hw_tag.prodid);
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100251 fdt_setprop(blob, 0, "toradex,product-id", prod_id, 5);
252
253 fdt_setprop(blob, 0, "toradex,board-rev", tdx_board_rev_str,
254 strlen(tdx_board_rev_str) + 1);
255 }
256
257 return 0;
258}
259#endif
260
261#else /* CONFIG_TDX_CFG_BLOCK */
262
Tom Rini4cc38852021-08-30 09:16:30 -0400263#if defined(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)
264u32 get_board_revision(void)
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100265{
266 return 0;
267}
268#endif /* CONFIG_REVISION_TAG */
269
270#ifdef CONFIG_SERIAL_TAG
271u32 get_board_serial(void)
272{
273 return 0;
274}
275#endif /* CONFIG_SERIAL_TAG */
276
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +0900277int ft_common_board_setup(void *blob, struct bd_info *bd)
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100278{
279 return 0;
280}
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100281
282#endif /* CONFIG_TDX_CFG_BLOCK */