blob: 57d7009e8c7f57c1a112804b3077a63d48844828 [file] [log] [blame]
Jan Kiszka8ff2ff82021-09-18 08:17:53 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Board specific initialization for IOT2050
4 * Copyright (c) Siemens AG, 2018-2021
5 *
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>
14#include <i2c.h>
15#include <led.h>
16#include <malloc.h>
17#include <net.h>
18#include <phy.h>
19#include <spl.h>
20#include <version.h>
21#include <linux/delay.h>
22#include <asm/arch/sys_proto.h>
23#include <asm/arch/hardware.h>
24#include <asm/gpio.h>
25#include <asm/io.h>
26
27#define IOT2050_INFO_MAGIC 0x20502050
28
29struct iot2050_info {
30 u32 magic;
31 u16 size;
32 char name[20 + 1];
33 char serial[16 + 1];
34 char mlfb[18 + 1];
35 char uuid[32 + 1];
36 char a5e[18 + 1];
37 u8 mac_addr_cnt;
38 u8 mac_addr[8][ARP_HLEN];
39 char seboot_version[40 + 1];
40} __packed;
41
42/*
43 * Scratch SRAM (available before DDR RAM) contains extracted EEPROM data.
44 */
45#define IOT2050_INFO_DATA ((struct iot2050_info *) \
46 TI_SRAM_SCRATCH_BOARD_EEPROM_START)
47
48DECLARE_GLOBAL_DATA_PTR;
49
50static bool board_is_advanced(void)
51{
52 struct iot2050_info *info = IOT2050_INFO_DATA;
53
54 return info->magic == IOT2050_INFO_MAGIC &&
55 strstr((char *)info->name, "IOT2050-ADVANCED") != NULL;
56}
57
Jan Kiszka8ff2ff82021-09-18 08:17:53 +020058static void remove_mmc1_target(void)
59{
60 char *boot_targets = strdup(env_get("boot_targets"));
61 char *mmc1 = strstr(boot_targets, "mmc1");
62
63 if (mmc1) {
64 memmove(mmc1, mmc1 + 4, strlen(mmc1 + 4) + 1);
65 env_set("boot_targets", boot_targets);
66 }
67
68 free(boot_targets);
69}
70
71void set_board_info_env(void)
72{
73 struct iot2050_info *info = IOT2050_INFO_DATA;
74 u8 __maybe_unused mac_cnt;
75 const char *fdtfile;
76
77 if (info->magic != IOT2050_INFO_MAGIC) {
78 pr_err("IOT2050: Board info parsing error!\n");
79 return;
80 }
81
82 if (env_get("board_uuid"))
83 return;
84
85 env_set("board_name", info->name);
86 env_set("board_serial", info->serial);
87 env_set("mlfb", info->mlfb);
88 env_set("board_uuid", info->uuid);
89 env_set("board_a5e", info->a5e);
90 env_set("fw_version", PLAIN_VERSION);
91 env_set("seboot_version", info->seboot_version);
92
93 if (IS_ENABLED(CONFIG_NET)) {
94 /* set MAC addresses to ensure forwarding to the OS */
95 for (mac_cnt = 0; mac_cnt < info->mac_addr_cnt; mac_cnt++) {
96 if (is_valid_ethaddr(info->mac_addr[mac_cnt]))
97 eth_env_set_enetaddr_by_index("eth",
98 mac_cnt + 1,
99 info->mac_addr[mac_cnt]);
100 }
101 }
102
103 if (board_is_advanced()) {
Su Baocheng0dcd3372023-02-28 19:19:09 +0100104 if (IS_ENABLED(CONFIG_TARGET_IOT2050_A53_PG1))
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200105 fdtfile = "ti/k3-am6548-iot2050-advanced.dtb";
106 else
107 fdtfile = "ti/k3-am6548-iot2050-advanced-pg2.dtb";
108 } else {
Su Baocheng0dcd3372023-02-28 19:19:09 +0100109 if (IS_ENABLED(CONFIG_TARGET_IOT2050_A53_PG1))
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200110 fdtfile = "ti/k3-am6528-iot2050-basic.dtb";
111 else
112 fdtfile = "ti/k3-am6528-iot2050-basic-pg2.dtb";
113 /* remove the unavailable eMMC (mmc1) from the list */
114 remove_mmc1_target();
115 }
116 env_set("fdtfile", fdtfile);
117
118 env_save();
119}
120
121int board_init(void)
122{
123 return 0;
124}
125
126int dram_init(void)
127{
128 if (board_is_advanced())
129 gd->ram_size = SZ_2G;
130 else
131 gd->ram_size = SZ_1G;
132
133 return 0;
134}
135
136int dram_init_banksize(void)
137{
138 dram_init();
139
140 /* Bank 0 declares the memory available in the DDR low region */
Tom Rinibb4dd962022-11-16 13:10:37 -0500141 gd->bd->bi_dram[0].start = CFG_SYS_SDRAM_BASE;
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200142 gd->bd->bi_dram[0].size = gd->ram_size;
143
144 /* Bank 1 declares the memory available in the DDR high region */
145 gd->bd->bi_dram[1].start = 0;
146 gd->bd->bi_dram[1].size = 0;
147
148 return 0;
149}
150
151#ifdef CONFIG_SPL_LOAD_FIT
152int board_fit_config_name_match(const char *name)
153{
154 struct iot2050_info *info = IOT2050_INFO_DATA;
155 char upper_name[32];
156
Su Baocheng8999cc52023-02-28 19:19:10 +0100157 /* skip the prefix "k3-am65x8-" */
158 name += 10;
159
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200160 if (info->magic != IOT2050_INFO_MAGIC ||
161 strlen(name) >= sizeof(upper_name))
162 return -1;
163
164 str_to_upper(name, upper_name, sizeof(upper_name));
165 if (!strcmp(upper_name, (char *)info->name))
166 return 0;
167
168 return -1;
169}
170#endif
171
172int do_board_detect(void)
173{
174 return 0;
175}
176
177#ifdef CONFIG_IOT2050_BOOT_SWITCH
178static bool user_button_pressed(void)
179{
180 struct udevice *red_led = NULL;
181 unsigned long count = 0;
182 struct gpio_desc gpio;
183
184 memset(&gpio, 0, sizeof(gpio));
185
186 if (dm_gpio_lookup_name("25", &gpio) < 0 ||
187 dm_gpio_request(&gpio, "USER button") < 0 ||
188 dm_gpio_set_dir_flags(&gpio, GPIOD_IS_IN) < 0)
189 return false;
190
191 if (dm_gpio_get_value(&gpio) == 1)
192 return false;
193
194 printf("USER button pressed - booting from external media only\n");
195
196 led_get_by_label("status-led-red", &red_led);
197
198 if (red_led)
199 led_set_state(red_led, LEDST_ON);
200
201 while (dm_gpio_get_value(&gpio) == 0 && count++ < 10000)
202 mdelay(1);
203
204 if (red_led)
205 led_set_state(red_led, LEDST_OFF);
206
207 return true;
208}
209#endif
210
211#define SERDES0_LANE_SELECT 0x00104080
212
213int board_late_init(void)
214{
215 /* change CTRL_MMR register to let serdes0 not output USB3.0 signals. */
216 writel(0x3, SERDES0_LANE_SELECT);
217
218 set_board_info_env();
219
220 /* remove the eMMC if requested via button */
221 if (IS_ENABLED(CONFIG_IOT2050_BOOT_SWITCH) && board_is_advanced() &&
222 user_button_pressed())
223 remove_mmc1_target();
224
225 return 0;
226}
227
228#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
229int ft_board_setup(void *blob, struct bd_info *bd)
230{
231 int ret;
232
233 ret = fdt_fixup_msmc_ram(blob, "/bus@100000", "sram@70000000");
234 if (ret < 0)
235 ret = fdt_fixup_msmc_ram(blob, "/interconnect@100000",
236 "sram@70000000");
237 if (ret)
238 pr_err("%s: fixing up msmc ram failed %d\n", __func__, ret);
239
240 return ret;
241}
242#endif
243
244void spl_board_init(void)
245{
246}
247
Marek Vasut98154342021-10-23 03:06:03 +0200248#if CONFIG_IS_ENABLED(LED) && CONFIG_IS_ENABLED(SHOW_BOOT_PROGRESS)
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200249/*
250 * Indicate any error or (accidental?) entering of CLI via the red status LED.
251 */
252void show_boot_progress(int progress)
253{
254 struct udevice *dev;
255 int ret;
256
Jan Kiszkaa8ea4f42021-11-03 15:12:30 +0100257 if ((progress < 0 && progress != -BOOTSTAGE_ID_NET_ETH_START) ||
258 progress == BOOTSTAGE_ID_ENTER_CLI_LOOP) {
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200259 ret = led_get_by_label("status-led-green", &dev);
260 if (ret == 0)
261 led_set_state(dev, LEDST_OFF);
262
263 ret = led_get_by_label("status-led-red", &dev);
264 if (ret == 0)
265 led_set_state(dev, LEDST_ON);
266 }
267}
268#endif