blob: 9f09788137d595368b0301e3d8ed627d12176764 [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");
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100129
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100130 /* Board can run even if config block is not present */
131 return 0;
132 }
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100133
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100134 snprintf(tdx_serial_str, sizeof(tdx_serial_str),
135 "%08u", tdx_serial);
136 snprintf(tdx_board_rev_str, sizeof(tdx_board_rev_str),
137 "V%1d.%1d%s",
138 tdx_hw_tag.ver_major,
139 tdx_hw_tag.ver_minor,
140 get_board_assembly(tdx_hw_tag.ver_assembly));
141
142 env_set("serial#", tdx_serial_str);
143
Igor Opaniukecfe0f52020-07-15 13:30:57 +0300144#ifdef CONFIG_TDX_CFG_BLOCK_EXTRA
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100145 if (read_tdx_cfg_block_carrier()) {
146 printf("MISSING TORADEX CARRIER CONFIG BLOCKS\n");
147 try_migrate_tdx_cfg_block_carrier();
148 } else {
149 tdx_carrier_board_name =
150 get_toradex_carrier_boards(tdx_car_hw_tag.prodid);
Igor Opaniukecfe0f52020-07-15 13:30:57 +0300151
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100152 snprintf(tdx_car_serial_str, sizeof(tdx_car_serial_str),
153 "%08u", tdx_car_serial);
154 snprintf(tdx_car_rev_str, sizeof(tdx_car_rev_str),
155 "V%1d.%1d%s",
156 tdx_car_hw_tag.ver_major,
157 tdx_car_hw_tag.ver_minor,
158 get_board_assembly(tdx_car_hw_tag.ver_assembly));
Igor Opaniukecfe0f52020-07-15 13:30:57 +0300159
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100160 env_set("carrier_serial#", tdx_car_serial_str);
Bhuvanchandra DV2190ade2019-03-25 17:18:28 +0100161 }
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100162#endif
Emanuele Ghidoli1e9459e2024-02-23 10:11:38 +0100163
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100164 /*
165 * Check if environment contains a valid MAC address,
166 * set the one from config block if not
167 */
Simon Glass399a9ce2017-08-03 12:22:14 -0600168 if (!eth_env_get_enetaddr("ethaddr", ethaddr))
Simon Glass8551d552017-08-03 12:22:11 -0600169 eth_env_set_enetaddr("ethaddr", (u8 *)&tdx_eth_addr);
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100170
Francesco Dolcini14163d62022-07-21 15:17:36 +0200171 if (IS_ENABLED(CONFIG_TDX_CFG_BLOCK_2ND_ETHADDR) &&
172 !eth_env_get_enetaddr("eth1addr", ethaddr)) {
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100173 /*
174 * Secondary MAC address is allocated from block
175 * 0x100000 higher then the first MAC address
176 */
177 memcpy(ethaddr, &tdx_eth_addr, 6);
178 ethaddr[3] += 0x10;
Simon Glass8551d552017-08-03 12:22:11 -0600179 eth_env_set_enetaddr("eth1addr", ethaddr);
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100180 }
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100181
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100182 return 0;
183}
Emanuele Ghidoli1121f342024-02-23 10:11:39 +0100184EVENT_SPY_SIMPLE(EVT_SETTINGS_R, settings_r);
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100185
Emanuele Ghidoli26b5cba2024-02-23 10:11:41 +0100186static int tdx_detect(struct udevice *dev)
187{
188 return valid_cfgblock ? 0 : -EINVAL;
189}
190
191static int tdx_get_str(struct udevice *dev, int id, size_t size, char *val)
192{
193 int ret = -ENOTSUPP;
194
195 switch (id) {
196 case SYSINFO_ID_BOARD_MODEL:
197 snprintf(val, size,
198 "Toradex %04d %s %s",
199 tdx_hw_tag.prodid,
200 toradex_modules[tdx_hw_tag.prodid].name,
201 tdx_board_rev_str);
202
203 ret = 0;
204 }
205
206 return ret;
207}
208
209static const struct udevice_id sysinfo_tdx_ids[] = {
210 { .compatible = "toradex,sysinfo" },
211 { /* sentinel */ }
212};
213
214static const struct sysinfo_ops sysinfo_tdx_ops = {
215 .detect = tdx_detect,
216 .get_str = tdx_get_str,
217};
218
219U_BOOT_DRIVER(sysinfo_toradex) = {
220 .name = "sysinfo_toradex",
221 .id = UCLASS_SYSINFO,
222 .of_match = sysinfo_tdx_ids,
223 .ops = &sysinfo_tdx_ops,
224};
225
Stefan Agner57985bd2021-07-23 09:39:46 +0300226#ifdef CONFIG_TDX_CFG_BLOCK_USB_GADGET_PID
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100227int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
228{
229 unsigned short usb_pid;
230
231 usb_pid = TORADEX_USB_PRODUCT_NUM_OFFSET + tdx_hw_tag.prodid;
232 put_unaligned(usb_pid, &dev->idProduct);
233
234 return 0;
235}
Stefan Agnera1886522016-11-30 13:41:52 -0800236#endif
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100237
Stefan Agner98ffd0f2016-11-30 13:41:53 -0800238#if defined(CONFIG_OF_LIBFDT)
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +0900239int ft_common_board_setup(void *blob, struct bd_info *bd)
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100240{
241 if (tdx_serial) {
242 fdt_setprop(blob, 0, "serial-number", tdx_serial_str,
243 strlen(tdx_serial_str) + 1);
244 }
245
246 if (tdx_hw_tag.ver_major) {
247 char prod_id[5];
248
Philippe Schenker38cf79e2022-06-13 19:35:21 +0200249 snprintf(prod_id, sizeof(prod_id), "%04u", tdx_hw_tag.prodid);
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100250 fdt_setprop(blob, 0, "toradex,product-id", prod_id, 5);
251
252 fdt_setprop(blob, 0, "toradex,board-rev", tdx_board_rev_str,
253 strlen(tdx_board_rev_str) + 1);
254 }
255
256 return 0;
257}
258#endif
259
260#else /* CONFIG_TDX_CFG_BLOCK */
261
Tom Rini4cc38852021-08-30 09:16:30 -0400262#if defined(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)
263u32 get_board_revision(void)
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100264{
265 return 0;
266}
267#endif /* CONFIG_REVISION_TAG */
268
269#ifdef CONFIG_SERIAL_TAG
270u32 get_board_serial(void)
271{
272 return 0;
273}
274#endif /* CONFIG_SERIAL_TAG */
275
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +0900276int ft_common_board_setup(void *blob, struct bd_info *bd)
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100277{
278 return 0;
279}
Marcel Ziswiler7a28dfc2016-11-16 17:49:22 +0100280
281#endif /* CONFIG_TDX_CFG_BLOCK */