blob: b2110978ae053353c2abcf9e8696dfe1f245feb0 [file] [log] [blame]
Jan Kiszkaa2db09e2021-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
58static bool board_is_sr1(void)
59{
60 struct iot2050_info *info = IOT2050_INFO_DATA;
61
62 return info->magic == IOT2050_INFO_MAGIC &&
63 !strstr((char *)info->name, "-PG2");
64}
65
66static void remove_mmc1_target(void)
67{
68 char *boot_targets = strdup(env_get("boot_targets"));
69 char *mmc1 = strstr(boot_targets, "mmc1");
70
71 if (mmc1) {
72 memmove(mmc1, mmc1 + 4, strlen(mmc1 + 4) + 1);
73 env_set("boot_targets", boot_targets);
74 }
75
76 free(boot_targets);
77}
78
79void set_board_info_env(void)
80{
81 struct iot2050_info *info = IOT2050_INFO_DATA;
82 u8 __maybe_unused mac_cnt;
83 const char *fdtfile;
84
85 if (info->magic != IOT2050_INFO_MAGIC) {
86 pr_err("IOT2050: Board info parsing error!\n");
87 return;
88 }
89
90 if (env_get("board_uuid"))
91 return;
92
93 env_set("board_name", info->name);
94 env_set("board_serial", info->serial);
95 env_set("mlfb", info->mlfb);
96 env_set("board_uuid", info->uuid);
97 env_set("board_a5e", info->a5e);
98 env_set("fw_version", PLAIN_VERSION);
99 env_set("seboot_version", info->seboot_version);
100
101 if (IS_ENABLED(CONFIG_NET)) {
102 /* set MAC addresses to ensure forwarding to the OS */
103 for (mac_cnt = 0; mac_cnt < info->mac_addr_cnt; mac_cnt++) {
104 if (is_valid_ethaddr(info->mac_addr[mac_cnt]))
105 eth_env_set_enetaddr_by_index("eth",
106 mac_cnt + 1,
107 info->mac_addr[mac_cnt]);
108 }
109 }
110
111 if (board_is_advanced()) {
112 if (board_is_sr1())
113 fdtfile = "ti/k3-am6548-iot2050-advanced.dtb";
114 else
115 fdtfile = "ti/k3-am6548-iot2050-advanced-pg2.dtb";
116 } else {
117 if (board_is_sr1())
118 fdtfile = "ti/k3-am6528-iot2050-basic.dtb";
119 else
120 fdtfile = "ti/k3-am6528-iot2050-basic-pg2.dtb";
121 /* remove the unavailable eMMC (mmc1) from the list */
122 remove_mmc1_target();
123 }
124 env_set("fdtfile", fdtfile);
125
126 env_save();
127}
128
129int board_init(void)
130{
131 return 0;
132}
133
134int dram_init(void)
135{
136 if (board_is_advanced())
137 gd->ram_size = SZ_2G;
138 else
139 gd->ram_size = SZ_1G;
140
141 return 0;
142}
143
144int dram_init_banksize(void)
145{
146 dram_init();
147
148 /* Bank 0 declares the memory available in the DDR low region */
149 gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
150 gd->bd->bi_dram[0].size = gd->ram_size;
151
152 /* Bank 1 declares the memory available in the DDR high region */
153 gd->bd->bi_dram[1].start = 0;
154 gd->bd->bi_dram[1].size = 0;
155
156 return 0;
157}
158
159#ifdef CONFIG_SPL_LOAD_FIT
160int board_fit_config_name_match(const char *name)
161{
162 struct iot2050_info *info = IOT2050_INFO_DATA;
163 char upper_name[32];
164
165 if (info->magic != IOT2050_INFO_MAGIC ||
166 strlen(name) >= sizeof(upper_name))
167 return -1;
168
169 str_to_upper(name, upper_name, sizeof(upper_name));
170 if (!strcmp(upper_name, (char *)info->name))
171 return 0;
172
173 return -1;
174}
175#endif
176
177int do_board_detect(void)
178{
179 return 0;
180}
181
182#ifdef CONFIG_IOT2050_BOOT_SWITCH
183static bool user_button_pressed(void)
184{
185 struct udevice *red_led = NULL;
186 unsigned long count = 0;
187 struct gpio_desc gpio;
188
189 memset(&gpio, 0, sizeof(gpio));
190
191 if (dm_gpio_lookup_name("25", &gpio) < 0 ||
192 dm_gpio_request(&gpio, "USER button") < 0 ||
193 dm_gpio_set_dir_flags(&gpio, GPIOD_IS_IN) < 0)
194 return false;
195
196 if (dm_gpio_get_value(&gpio) == 1)
197 return false;
198
199 printf("USER button pressed - booting from external media only\n");
200
201 led_get_by_label("status-led-red", &red_led);
202
203 if (red_led)
204 led_set_state(red_led, LEDST_ON);
205
206 while (dm_gpio_get_value(&gpio) == 0 && count++ < 10000)
207 mdelay(1);
208
209 if (red_led)
210 led_set_state(red_led, LEDST_OFF);
211
212 return true;
213}
214#endif
215
216#define SERDES0_LANE_SELECT 0x00104080
217
218int board_late_init(void)
219{
220 /* change CTRL_MMR register to let serdes0 not output USB3.0 signals. */
221 writel(0x3, SERDES0_LANE_SELECT);
222
223 set_board_info_env();
224
225 /* remove the eMMC if requested via button */
226 if (IS_ENABLED(CONFIG_IOT2050_BOOT_SWITCH) && board_is_advanced() &&
227 user_button_pressed())
228 remove_mmc1_target();
229
230 return 0;
231}
232
233#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
234int ft_board_setup(void *blob, struct bd_info *bd)
235{
236 int ret;
237
238 ret = fdt_fixup_msmc_ram(blob, "/bus@100000", "sram@70000000");
239 if (ret < 0)
240 ret = fdt_fixup_msmc_ram(blob, "/interconnect@100000",
241 "sram@70000000");
242 if (ret)
243 pr_err("%s: fixing up msmc ram failed %d\n", __func__, ret);
244
245 return ret;
246}
247#endif
248
249void spl_board_init(void)
250{
251}
252
253#if CONFIG_IS_ENABLED(LED) && CONFIG_IS_ENABLED(BOOTSTAGE)
254/*
255 * Indicate any error or (accidental?) entering of CLI via the red status LED.
256 */
257void show_boot_progress(int progress)
258{
259 struct udevice *dev;
260 int ret;
261
262 if (progress < 0 || progress == BOOTSTAGE_ID_ENTER_CLI_LOOP) {
263 ret = led_get_by_label("status-led-green", &dev);
264 if (ret == 0)
265 led_set_state(dev, LEDST_OFF);
266
267 ret = led_get_by_label("status-led-red", &dev);
268 if (ret == 0)
269 led_set_state(dev, LEDST_ON);
270 }
271}
272#endif