blob: df705b7c97181b7fdbac502b86852a0eccd953ea [file] [log] [blame]
Jan Kiszka8ff2ff82021-09-18 08:17:53 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Board specific initialization for IOT2050
Jan Kiszkae31f16c2023-02-28 19:19:23 +01004 * Copyright (c) Siemens AG, 2018-2022
Jan Kiszka8ff2ff82021-09-18 08:17:53 +02005 *
6 * Authors:
7 * Le Jin <le.jin@siemens.com>
8 * Jan Kiszka <jan.kiszka@siemens.com>
9 */
10
11#include <common.h>
12#include <bootstage.h>
13#include <dm.h>
Jan Kiszkae31f16c2023-02-28 19:19:23 +010014#include <fdt_support.h>
Jan Kiszka8ff2ff82021-09-18 08:17:53 +020015#include <i2c.h>
16#include <led.h>
17#include <malloc.h>
Jan Kiszkae31f16c2023-02-28 19:19:23 +010018#include <mapmem.h>
Jan Kiszka8ff2ff82021-09-18 08:17:53 +020019#include <net.h>
20#include <phy.h>
21#include <spl.h>
22#include <version.h>
23#include <linux/delay.h>
24#include <asm/arch/sys_proto.h>
25#include <asm/arch/hardware.h>
26#include <asm/gpio.h>
27#include <asm/io.h>
28
29#define IOT2050_INFO_MAGIC 0x20502050
30
31struct iot2050_info {
32 u32 magic;
33 u16 size;
34 char name[20 + 1];
35 char serial[16 + 1];
36 char mlfb[18 + 1];
37 char uuid[32 + 1];
38 char a5e[18 + 1];
39 u8 mac_addr_cnt;
40 u8 mac_addr[8][ARP_HLEN];
41 char seboot_version[40 + 1];
42} __packed;
43
44/*
45 * Scratch SRAM (available before DDR RAM) contains extracted EEPROM data.
46 */
47#define IOT2050_INFO_DATA ((struct iot2050_info *) \
48 TI_SRAM_SCRATCH_BOARD_EEPROM_START)
49
50DECLARE_GLOBAL_DATA_PTR;
51
Jan Kiszkae31f16c2023-02-28 19:19:23 +010052struct gpio_config {
53 const char *gpio_name;
54 const char *label;
55};
56
57enum m2_connector_mode {
58 BKEY_PCIEX2 = 0,
59 BKEY_PCIE_EKEY_PCIE,
60 BKEY_USB30_EKEY_PCIE,
61 CONNECTOR_MODE_INVALID
62};
63
64struct m2_config_pins {
65 int config[4];
66};
67
68struct serdes_mux_control {
69 int ctrl_usb30_pcie0_lane0;
70 int ctrl_pcie1_pcie0;
71 int ctrl_usb30_pcie0_lane1;
72};
73
74struct m2_config_table {
75 struct m2_config_pins config_pins;
76 enum m2_connector_mode mode;
77};
78
79static const struct gpio_config serdes_mux_ctl_pin_info[] = {
80 {"gpio@600000_88", "CTRL_USB30_PCIE0_LANE0"},
81 {"gpio@600000_82", "CTRL_PCIE1_PCIE0"},
82 {"gpio@600000_89", "CTRL_USB30_PCIE0_LANE1"},
83};
84
85static const struct gpio_config m2_bkey_cfg_pin_info[] = {
86 {"gpio@601000_18", "KEY_CONFIG_0"},
87 {"gpio@601000_19", "KEY_CONFIG_1"},
88 {"gpio@601000_88", "KEY_CONFIG_2"},
89 {"gpio@601000_89", "KEY_CONFIG_3"},
90};
91
92static const struct m2_config_table m2_config_table[] = {
93 {{{0, 1, 0, 0}}, BKEY_PCIEX2},
94 {{{0, 0, 1, 0}}, BKEY_PCIE_EKEY_PCIE},
95 {{{0, 1, 1, 0}}, BKEY_PCIE_EKEY_PCIE},
96 {{{1, 0, 0, 1}}, BKEY_PCIE_EKEY_PCIE},
97 {{{1, 1, 0, 1}}, BKEY_PCIE_EKEY_PCIE},
98 {{{0, 0, 0, 1}}, BKEY_USB30_EKEY_PCIE},
99 {{{0, 1, 0, 1}}, BKEY_USB30_EKEY_PCIE},
100 {{{0, 0, 1, 1}}, BKEY_USB30_EKEY_PCIE},
101 {{{0, 1, 1, 1}}, BKEY_USB30_EKEY_PCIE},
102 {{{1, 0, 1, 1}}, BKEY_USB30_EKEY_PCIE},
103};
104
105static const struct serdes_mux_control serdes_mux_ctrl[] = {
106 [BKEY_PCIEX2] = {0, 0, 1},
107 [BKEY_PCIE_EKEY_PCIE] = {0, 1, 0},
108 [BKEY_USB30_EKEY_PCIE] = {1, 1, 0},
109};
110
111static const char *m2_connector_mode_name[] = {
112 [BKEY_PCIEX2] = "PCIe x2 (key B)",
113 [BKEY_PCIE_EKEY_PCIE] = "PCIe (key B) / PCIe (key E)",
114 [BKEY_USB30_EKEY_PCIE] = "USB 3.0 (key B) / PCIe (key E)",
115};
116
117static enum m2_connector_mode connector_mode;
118
119#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
120static void *connector_overlay;
121static u32 connector_overlay_size;
122#endif
123
124static int get_pinvalue(const char *gpio_name, const char *label)
125{
126 struct gpio_desc gpio;
127
128 if (dm_gpio_lookup_name(gpio_name, &gpio) < 0 ||
129 dm_gpio_request(&gpio, label) < 0 ||
130 dm_gpio_set_dir_flags(&gpio, GPIOD_IS_IN) < 0) {
131 pr_err("Cannot get pin %s for M.2 configuration\n", gpio_name);
132 return 0;
133 }
134
135 return dm_gpio_get_value(&gpio);
136}
137
138static void set_pinvalue(const char *gpio_name, const char *label, int value)
139{
140 struct gpio_desc gpio;
141
142 if (dm_gpio_lookup_name(gpio_name, &gpio) < 0 ||
143 dm_gpio_request(&gpio, label) < 0 ||
144 dm_gpio_set_dir_flags(&gpio, GPIOD_IS_OUT) < 0) {
145 pr_err("Cannot set pin %s for M.2 configuration\n", gpio_name);
146 return;
147 }
148 dm_gpio_set_value(&gpio, value);
149}
150
151static bool board_is_m2(void)
152{
153 struct iot2050_info *info = IOT2050_INFO_DATA;
154
155 return IS_ENABLED(CONFIG_TARGET_IOT2050_A53_PG2) &&
156 info->magic == IOT2050_INFO_MAGIC &&
157 strcmp((char *)info->name, "IOT2050-ADVANCED-M2") == 0;
158}
159
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200160static bool board_is_advanced(void)
161{
162 struct iot2050_info *info = IOT2050_INFO_DATA;
163
164 return info->magic == IOT2050_INFO_MAGIC &&
165 strstr((char *)info->name, "IOT2050-ADVANCED") != NULL;
166}
167
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200168static void remove_mmc1_target(void)
169{
170 char *boot_targets = strdup(env_get("boot_targets"));
171 char *mmc1 = strstr(boot_targets, "mmc1");
172
173 if (mmc1) {
174 memmove(mmc1, mmc1 + 4, strlen(mmc1 + 4) + 1);
175 env_set("boot_targets", boot_targets);
176 }
177
178 free(boot_targets);
179}
180
181void set_board_info_env(void)
182{
183 struct iot2050_info *info = IOT2050_INFO_DATA;
184 u8 __maybe_unused mac_cnt;
185 const char *fdtfile;
186
187 if (info->magic != IOT2050_INFO_MAGIC) {
188 pr_err("IOT2050: Board info parsing error!\n");
189 return;
190 }
191
192 if (env_get("board_uuid"))
193 return;
194
195 env_set("board_name", info->name);
196 env_set("board_serial", info->serial);
197 env_set("mlfb", info->mlfb);
198 env_set("board_uuid", info->uuid);
199 env_set("board_a5e", info->a5e);
200 env_set("fw_version", PLAIN_VERSION);
201 env_set("seboot_version", info->seboot_version);
202
203 if (IS_ENABLED(CONFIG_NET)) {
204 /* set MAC addresses to ensure forwarding to the OS */
205 for (mac_cnt = 0; mac_cnt < info->mac_addr_cnt; mac_cnt++) {
206 if (is_valid_ethaddr(info->mac_addr[mac_cnt]))
207 eth_env_set_enetaddr_by_index("eth",
208 mac_cnt + 1,
209 info->mac_addr[mac_cnt]);
210 }
211 }
212
213 if (board_is_advanced()) {
Su Baocheng0dcd3372023-02-28 19:19:09 +0100214 if (IS_ENABLED(CONFIG_TARGET_IOT2050_A53_PG1))
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200215 fdtfile = "ti/k3-am6548-iot2050-advanced.dtb";
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100216 else if(board_is_m2())
217 fdtfile = "ti/k3-am6548-iot2050-advanced-m2.dtb";
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200218 else
219 fdtfile = "ti/k3-am6548-iot2050-advanced-pg2.dtb";
220 } else {
Su Baocheng0dcd3372023-02-28 19:19:09 +0100221 if (IS_ENABLED(CONFIG_TARGET_IOT2050_A53_PG1))
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200222 fdtfile = "ti/k3-am6528-iot2050-basic.dtb";
223 else
224 fdtfile = "ti/k3-am6528-iot2050-basic-pg2.dtb";
225 /* remove the unavailable eMMC (mmc1) from the list */
226 remove_mmc1_target();
227 }
228 env_set("fdtfile", fdtfile);
229
230 env_save();
231}
232
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100233static void m2_overlay_prepare(void)
234{
235#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
236 const char *overlay_path;
237 void *overlay;
238 u64 loadaddr;
239 ofnode node;
240 int ret;
241
242 if (connector_mode == BKEY_PCIEX2)
243 return;
244
245 if (connector_mode == BKEY_PCIE_EKEY_PCIE)
246 overlay_path = "/fit-images/bkey-ekey-pcie-overlay";
247 else
248 overlay_path = "/fit-images/bkey-usb3-overlay";
249
250 node = ofnode_path(overlay_path);
251 if (!ofnode_valid(node))
252 goto fit_error;
253
254 ret = ofnode_read_u64(node, "load", &loadaddr);
255 if (ret)
256 goto fit_error;
257
258 ret = ofnode_read_u32(node, "size", &connector_overlay_size);
259 if (ret)
260 goto fit_error;
261
262 overlay = map_sysmem(loadaddr, connector_overlay_size);
263
264 connector_overlay = malloc(connector_overlay_size);
265 if (!connector_overlay)
266 goto fit_error;
267
268 memcpy(connector_overlay, overlay, connector_overlay_size);
269 return;
270
271fit_error:
272 pr_err("M.2 device tree overlay %s not available,\n", overlay_path);
273#endif
274}
275
276static void m2_connector_setup(void)
277{
278 ulong m2_manual_config = env_get_ulong("m2_manual_config", 10,
279 CONNECTOR_MODE_INVALID);
280 const char *mode_info = "";
281 struct m2_config_pins config_pins;
282 unsigned int n;
283
284 /* enable M.2 connector power */
285 set_pinvalue("gpio@601000_17", "P3V3_M2_EN", 1);
286 udelay(4 * 100);
287
288 if (m2_manual_config < CONNECTOR_MODE_INVALID) {
289 mode_info = " [manual mode]";
290 connector_mode = m2_manual_config;
291 } else { /* auto detection */
292 for (n = 0; n < ARRAY_SIZE(config_pins.config); n++)
293 config_pins.config[n] =
294 get_pinvalue(m2_bkey_cfg_pin_info[n].gpio_name,
295 m2_bkey_cfg_pin_info[n].label);
296 connector_mode = CONNECTOR_MODE_INVALID;
297 for (n = 0; n < ARRAY_SIZE(m2_config_table); n++) {
298 if (!memcmp(config_pins.config,
299 m2_config_table[n].config_pins.config,
300 sizeof(config_pins.config))) {
301 connector_mode = m2_config_table[n].mode;
302 break;
303 }
304 }
305 if (connector_mode == CONNECTOR_MODE_INVALID) {
306 mode_info = " [fallback, card unknown/unsupported]";
307 connector_mode = BKEY_USB30_EKEY_PCIE;
308 }
309 }
310
311 printf("M.2: %s%s\n", m2_connector_mode_name[connector_mode],
312 mode_info);
313
314 /* configure serdes mux */
315 set_pinvalue(serdes_mux_ctl_pin_info[0].gpio_name,
316 serdes_mux_ctl_pin_info[0].label,
317 serdes_mux_ctrl[connector_mode].ctrl_usb30_pcie0_lane0);
318 set_pinvalue(serdes_mux_ctl_pin_info[1].gpio_name,
319 serdes_mux_ctl_pin_info[1].label,
320 serdes_mux_ctrl[connector_mode].ctrl_pcie1_pcie0);
321 set_pinvalue(serdes_mux_ctl_pin_info[2].gpio_name,
322 serdes_mux_ctl_pin_info[2].label,
323 serdes_mux_ctrl[connector_mode].ctrl_usb30_pcie0_lane1);
324
325 m2_overlay_prepare();
326}
327
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200328int board_init(void)
329{
330 return 0;
331}
332
333int dram_init(void)
334{
335 if (board_is_advanced())
336 gd->ram_size = SZ_2G;
337 else
338 gd->ram_size = SZ_1G;
339
340 return 0;
341}
342
343int dram_init_banksize(void)
344{
345 dram_init();
346
347 /* Bank 0 declares the memory available in the DDR low region */
Tom Rinibb4dd962022-11-16 13:10:37 -0500348 gd->bd->bi_dram[0].start = CFG_SYS_SDRAM_BASE;
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200349 gd->bd->bi_dram[0].size = gd->ram_size;
350
351 /* Bank 1 declares the memory available in the DDR high region */
352 gd->bd->bi_dram[1].start = 0;
353 gd->bd->bi_dram[1].size = 0;
354
355 return 0;
356}
357
358#ifdef CONFIG_SPL_LOAD_FIT
359int board_fit_config_name_match(const char *name)
360{
361 struct iot2050_info *info = IOT2050_INFO_DATA;
362 char upper_name[32];
363
Su Baocheng8999cc52023-02-28 19:19:10 +0100364 /* skip the prefix "k3-am65x8-" */
365 name += 10;
366
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200367 if (info->magic != IOT2050_INFO_MAGIC ||
368 strlen(name) >= sizeof(upper_name))
369 return -1;
370
371 str_to_upper(name, upper_name, sizeof(upper_name));
372 if (!strcmp(upper_name, (char *)info->name))
373 return 0;
374
375 return -1;
376}
377#endif
378
379int do_board_detect(void)
380{
381 return 0;
382}
383
384#ifdef CONFIG_IOT2050_BOOT_SWITCH
385static bool user_button_pressed(void)
386{
387 struct udevice *red_led = NULL;
388 unsigned long count = 0;
389 struct gpio_desc gpio;
390
391 memset(&gpio, 0, sizeof(gpio));
392
chao zeng7d933ad2023-02-28 19:19:20 +0100393 if (dm_gpio_lookup_name("gpio@42110000_25", &gpio) < 0 ||
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200394 dm_gpio_request(&gpio, "USER button") < 0 ||
395 dm_gpio_set_dir_flags(&gpio, GPIOD_IS_IN) < 0)
396 return false;
397
398 if (dm_gpio_get_value(&gpio) == 1)
399 return false;
400
401 printf("USER button pressed - booting from external media only\n");
402
403 led_get_by_label("status-led-red", &red_led);
404
405 if (red_led)
406 led_set_state(red_led, LEDST_ON);
407
408 while (dm_gpio_get_value(&gpio) == 0 && count++ < 10000)
409 mdelay(1);
410
411 if (red_led)
412 led_set_state(red_led, LEDST_OFF);
413
414 return true;
415}
416#endif
417
418#define SERDES0_LANE_SELECT 0x00104080
419
420int board_late_init(void)
421{
422 /* change CTRL_MMR register to let serdes0 not output USB3.0 signals. */
423 writel(0x3, SERDES0_LANE_SELECT);
424
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100425 if (board_is_m2())
426 m2_connector_setup();
427
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200428 set_board_info_env();
429
430 /* remove the eMMC if requested via button */
431 if (IS_ENABLED(CONFIG_IOT2050_BOOT_SWITCH) && board_is_advanced() &&
432 user_button_pressed())
433 remove_mmc1_target();
434
435 return 0;
436}
437
438#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100439static void m2_fdt_fixup(void *blob)
440{
441 void *overlay_copy = NULL;
442 void *fdt_copy = NULL;
443 u32 fdt_size;
444 int err;
445
446 if (!connector_overlay)
447 return;
448
449 /*
450 * We need to work with temporary copies here because fdt_overlay_apply
451 * is destructive to the overlay and also to the target blob, even if
452 * application fails.
453 */
454 fdt_size = fdt_totalsize(blob);
455 fdt_copy = malloc(fdt_size);
456 if (!fdt_copy)
457 goto fixup_error;
458
459 memcpy(fdt_copy, blob, fdt_size);
460
461 overlay_copy = malloc(connector_overlay_size);
462 if (!overlay_copy)
463 goto fixup_error;
464
465 memcpy(overlay_copy, connector_overlay, connector_overlay_size);
466
467 err = fdt_overlay_apply_verbose(fdt_copy, overlay_copy);
468 if (err)
469 goto fixup_error;
470
471 memcpy(blob, fdt_copy, fdt_size);
472
473cleanup:
474 free(fdt_copy);
475 free(overlay_copy);
476 return;
477
478fixup_error:
479 pr_err("Could not apply M.2 device tree overlay\n");
480 goto cleanup;
481}
482
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200483int ft_board_setup(void *blob, struct bd_info *bd)
484{
485 int ret;
486
487 ret = fdt_fixup_msmc_ram(blob, "/bus@100000", "sram@70000000");
488 if (ret < 0)
489 ret = fdt_fixup_msmc_ram(blob, "/interconnect@100000",
490 "sram@70000000");
491 if (ret)
492 pr_err("%s: fixing up msmc ram failed %d\n", __func__, ret);
493
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100494 if (board_is_m2())
495 m2_fdt_fixup(blob);
496
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200497 return ret;
498}
499#endif
500
501void spl_board_init(void)
502{
503}
504
Marek Vasut98154342021-10-23 03:06:03 +0200505#if CONFIG_IS_ENABLED(LED) && CONFIG_IS_ENABLED(SHOW_BOOT_PROGRESS)
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200506/*
507 * Indicate any error or (accidental?) entering of CLI via the red status LED.
508 */
509void show_boot_progress(int progress)
510{
511 struct udevice *dev;
512 int ret;
513
Jan Kiszkaa8ea4f42021-11-03 15:12:30 +0100514 if ((progress < 0 && progress != -BOOTSTAGE_ID_NET_ETH_START) ||
515 progress == BOOTSTAGE_ID_ENTER_CLI_LOOP) {
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200516 ret = led_get_by_label("status-led-green", &dev);
517 if (ret == 0)
518 led_set_state(dev, LEDST_OFF);
519
520 ret = led_get_by_label("status-led-red", &dev);
521 if (ret == 0)
522 led_set_state(dev, LEDST_ON);
523 }
524}
525#endif