]>
Commit | Line | Data |
---|---|---|
f8185032 LV |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Board specific initialization for J721E EVM | |
4 | * | |
5 | * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/ | |
6 | * Lokesh Vutla <lokeshvutla@ti.com> | |
7 | * | |
8 | */ | |
9 | ||
10 | #include <common.h> | |
09140113 | 11 | #include <env.h> |
4d72caa5 SG |
12 | #include <fdt_support.h> |
13 | #include <image.h> | |
67c4e9f8 | 14 | #include <init.h> |
90526e9f | 15 | #include <net.h> |
643eb6ea AD |
16 | #include <asm/arch/sys_proto.h> |
17 | #include <asm/arch/hardware.h> | |
18 | #include <asm/gpio.h> | |
f8185032 LV |
19 | #include <asm/io.h> |
20 | #include <spl.h> | |
d146af5b | 21 | #include <asm/arch/sys_proto.h> |
fa281f64 TK |
22 | #include <dm.h> |
23 | #include <dm/uclass-internal.h> | |
f8185032 | 24 | |
643eb6ea AD |
25 | #include "../common/board_detect.h" |
26 | ||
27 | #define board_is_j721e_som() (board_ti_k3_is("J721EX-PM1-SOM") || \ | |
28 | board_ti_k3_is("J721EX-PM2-SOM")) | |
29 | ||
30 | /* Max number of MAC addresses that are parsed/processed per daughter card */ | |
31 | #define DAUGHTER_CARD_NO_OF_MAC_ADDR 8 | |
32 | ||
f8185032 LV |
33 | DECLARE_GLOBAL_DATA_PTR; |
34 | ||
35 | int board_init(void) | |
36 | { | |
37 | return 0; | |
38 | } | |
39 | ||
40 | int dram_init(void) | |
41 | { | |
42 | #ifdef CONFIG_PHYS_64BIT | |
43 | gd->ram_size = 0x100000000; | |
44 | #else | |
45 | gd->ram_size = 0x80000000; | |
46 | #endif | |
47 | ||
48 | return 0; | |
49 | } | |
50 | ||
51 | ulong board_get_usable_ram_top(ulong total_size) | |
52 | { | |
53 | #ifdef CONFIG_PHYS_64BIT | |
54 | /* Limit RAM used by U-Boot to the DDR low region */ | |
55 | if (gd->ram_top > 0x100000000) | |
56 | return 0x100000000; | |
57 | #endif | |
58 | ||
59 | return gd->ram_top; | |
60 | } | |
61 | ||
62 | int dram_init_banksize(void) | |
63 | { | |
64 | /* Bank 0 declares the memory available in the DDR low region */ | |
65 | gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; | |
66 | gd->bd->bi_dram[0].size = 0x80000000; | |
67 | gd->ram_size = 0x80000000; | |
68 | ||
69 | #ifdef CONFIG_PHYS_64BIT | |
70 | /* Bank 1 declares the memory available in the DDR high region */ | |
71 | gd->bd->bi_dram[1].start = CONFIG_SYS_SDRAM_BASE1; | |
72 | gd->bd->bi_dram[1].size = 0x80000000; | |
73 | gd->ram_size = 0x100000000; | |
74 | #endif | |
75 | ||
76 | return 0; | |
77 | } | |
78 | ||
79 | #ifdef CONFIG_SPL_LOAD_FIT | |
80 | int board_fit_config_name_match(const char *name) | |
81 | { | |
82 | if (!strcmp(name, "k3-j721e-common-proc-board")) | |
83 | return 0; | |
84 | ||
85 | return -1; | |
86 | } | |
87 | #endif | |
d146af5b SA |
88 | |
89 | #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) | |
90 | int ft_board_setup(void *blob, bd_t *bd) | |
91 | { | |
92 | int ret; | |
93 | ||
94 | ret = fdt_fixup_msmc_ram(blob, "/interconnect@100000", "sram@70000000"); | |
95 | if (ret) | |
96 | printf("%s: fixing up msmc ram failed %d\n", __func__, ret); | |
97 | ||
98 | return ret; | |
99 | } | |
100 | #endif | |
643eb6ea AD |
101 | |
102 | int do_board_detect(void) | |
103 | { | |
104 | int ret; | |
105 | ||
106 | ret = ti_i2c_eeprom_am6_get_base(CONFIG_EEPROM_BUS_ADDRESS, | |
107 | CONFIG_EEPROM_CHIP_ADDRESS); | |
108 | if (ret) | |
109 | pr_err("Reading on-board EEPROM at 0x%02x failed %d\n", | |
110 | CONFIG_EEPROM_CHIP_ADDRESS, ret); | |
111 | ||
112 | return ret; | |
113 | } | |
114 | ||
c7068aba LV |
115 | int checkboard(void) |
116 | { | |
117 | struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; | |
118 | ||
119 | if (do_board_detect()) | |
120 | /* EEPROM not populated */ | |
121 | printf("Board: %s rev %s\n", "J721EX-PM1-SOM", "E2"); | |
122 | else | |
123 | printf("Board: %s rev %s\n", ep->name, ep->version); | |
124 | ||
125 | return 0; | |
126 | } | |
127 | ||
643eb6ea AD |
128 | static void setup_board_eeprom_env(void) |
129 | { | |
130 | char *name = "j721e"; | |
131 | ||
132 | if (do_board_detect()) | |
133 | goto invalid_eeprom; | |
134 | ||
135 | if (board_is_j721e_som()) | |
136 | name = "j721e"; | |
137 | else | |
138 | printf("Unidentified board claims %s in eeprom header\n", | |
139 | board_ti_get_name()); | |
140 | ||
141 | invalid_eeprom: | |
142 | set_board_info_env_am6(name); | |
143 | } | |
144 | ||
145 | static void setup_serial(void) | |
146 | { | |
147 | struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; | |
148 | unsigned long board_serial; | |
149 | char *endp; | |
150 | char serial_string[17] = { 0 }; | |
151 | ||
152 | if (env_get("serial#")) | |
153 | return; | |
154 | ||
155 | board_serial = simple_strtoul(ep->serial, &endp, 16); | |
156 | if (*endp != '\0') { | |
157 | pr_err("Error: Can't set serial# to %s\n", ep->serial); | |
158 | return; | |
159 | } | |
160 | ||
161 | snprintf(serial_string, sizeof(serial_string), "%016lx", board_serial); | |
162 | env_set("serial#", serial_string); | |
163 | } | |
164 | ||
165 | /* | |
166 | * Declaration of daughtercards to probe. Note that when adding more | |
167 | * cards they should be grouped by the 'i2c_addr' field to allow for a | |
168 | * more efficient probing process. | |
169 | */ | |
170 | static const struct { | |
171 | u8 i2c_addr; /* I2C address of card EEPROM */ | |
172 | char *card_name; /* EEPROM-programmed card name */ | |
173 | char *dtbo_name; /* Device tree overlay to apply */ | |
174 | u8 eth_offset; /* ethXaddr MAC address index offset */ | |
175 | } ext_cards[] = { | |
176 | { | |
177 | 0x51, | |
178 | "J7X-BASE-CPB", | |
179 | "", /* No dtbo for this board */ | |
180 | 0, | |
181 | }, | |
182 | { | |
183 | 0x52, | |
184 | "J7X-INFOTAN-EXP", | |
185 | "", /* No dtbo for this board */ | |
186 | 0, | |
187 | }, | |
188 | { | |
189 | 0x52, | |
190 | "J7X-GESI-EXP", | |
191 | "", /* No dtbo for this board */ | |
192 | 5, /* Start populating from eth5addr */ | |
193 | }, | |
194 | { | |
195 | 0x54, | |
196 | "J7X-VSC8514-ETH", | |
197 | "", /* No dtbo for this board */ | |
198 | 1, /* Start populating from eth1addr */ | |
199 | }, | |
200 | }; | |
201 | ||
202 | static bool daughter_card_detect_flags[ARRAY_SIZE(ext_cards)]; | |
203 | ||
204 | const char *board_fit_get_additionnal_images(int index, const char *type) | |
205 | { | |
206 | int i, j; | |
207 | ||
208 | if (strcmp(type, FIT_FDT_PROP)) | |
209 | return NULL; | |
210 | ||
211 | j = 0; | |
212 | for (i = 0; i < ARRAY_SIZE(ext_cards); i++) { | |
213 | if (daughter_card_detect_flags[i]) { | |
214 | if (j == index) { | |
215 | /* | |
216 | * Return dtbo name only if populated, | |
217 | * otherwise stop parsing here. | |
218 | */ | |
219 | if (strlen(ext_cards[i].dtbo_name)) | |
220 | return ext_cards[i].dtbo_name; | |
221 | else | |
222 | return NULL; | |
223 | }; | |
224 | ||
225 | j++; | |
226 | } | |
227 | } | |
228 | ||
229 | return NULL; | |
230 | } | |
231 | ||
232 | static int probe_daughtercards(void) | |
233 | { | |
234 | char mac_addr[DAUGHTER_CARD_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN]; | |
235 | bool eeprom_read_success; | |
236 | struct ti_am6_eeprom ep; | |
237 | u8 previous_i2c_addr; | |
238 | u8 mac_addr_cnt; | |
239 | int i; | |
240 | int ret; | |
241 | ||
242 | /* Mark previous I2C address variable as not populated */ | |
243 | previous_i2c_addr = 0xff; | |
244 | ||
245 | /* No EEPROM data was read yet */ | |
246 | eeprom_read_success = false; | |
247 | ||
248 | /* Iterate through list of daughtercards */ | |
249 | for (i = 0; i < ARRAY_SIZE(ext_cards); i++) { | |
250 | /* Obtain card-specific I2C address */ | |
251 | u8 i2c_addr = ext_cards[i].i2c_addr; | |
252 | ||
253 | /* Read card EEPROM if not already read previously */ | |
254 | if (i2c_addr != previous_i2c_addr) { | |
255 | /* Store I2C address so we can avoid reading twice */ | |
256 | previous_i2c_addr = i2c_addr; | |
257 | ||
258 | /* Get and parse the daughter card EEPROM record */ | |
259 | ret = ti_i2c_eeprom_am6_get(CONFIG_EEPROM_BUS_ADDRESS, | |
260 | i2c_addr, | |
261 | &ep, | |
262 | (char **)mac_addr, | |
263 | DAUGHTER_CARD_NO_OF_MAC_ADDR, | |
264 | &mac_addr_cnt); | |
265 | if (ret) { | |
266 | debug("%s: No daughtercard EEPROM at 0x%02x found %d\n", | |
267 | __func__, i2c_addr, ret); | |
268 | eeprom_read_success = false; | |
269 | /* Skip to the next daughtercard to probe */ | |
270 | continue; | |
271 | } | |
272 | ||
273 | /* EEPROM read successful, okay to further process. */ | |
274 | eeprom_read_success = true; | |
275 | } | |
276 | ||
277 | /* Only continue processing if EEPROM data was read */ | |
278 | if (!eeprom_read_success) | |
279 | continue; | |
280 | ||
281 | /* Only process the parsed data if we found a match */ | |
282 | if (strncmp(ep.name, ext_cards[i].card_name, sizeof(ep.name))) | |
283 | continue; | |
284 | ||
285 | printf("Detected: %s rev %s\n", ep.name, ep.version); | |
286 | daughter_card_detect_flags[i] = true; | |
287 | ||
288 | #ifndef CONFIG_SPL_BUILD | |
289 | int j; | |
290 | /* | |
291 | * Populate any MAC addresses from daughtercard into the U-Boot | |
292 | * environment, starting with a card-specific offset so we can | |
293 | * have multiple ext_cards contribute to the MAC pool in a well- | |
294 | * defined manner. | |
295 | */ | |
296 | for (j = 0; j < mac_addr_cnt; j++) { | |
297 | if (!is_valid_ethaddr((u8 *)mac_addr[j])) | |
298 | continue; | |
299 | ||
300 | eth_env_set_enetaddr_by_index("eth", | |
301 | ext_cards[i].eth_offset + j, | |
302 | (uchar *)mac_addr[j]); | |
303 | } | |
304 | #endif | |
305 | } | |
306 | #ifndef CONFIG_SPL_BUILD | |
307 | char name_overlays[1024] = { 0 }; | |
308 | ||
309 | for (i = 0; i < ARRAY_SIZE(ext_cards); i++) { | |
310 | if (!daughter_card_detect_flags[i]) | |
311 | continue; | |
312 | ||
313 | /* Skip if no overlays are to be added */ | |
314 | if (!strlen(ext_cards[i].dtbo_name)) | |
315 | continue; | |
316 | ||
317 | /* | |
318 | * Make sure we are not running out of buffer space by checking | |
319 | * if we can fit the new overlay, a trailing space to be used | |
320 | * as a separator, plus the terminating zero. | |
321 | */ | |
322 | if (strlen(name_overlays) + strlen(ext_cards[i].dtbo_name) + 2 > | |
323 | sizeof(name_overlays)) | |
324 | return -ENOMEM; | |
325 | ||
326 | /* Append to our list of overlays */ | |
327 | strcat(name_overlays, ext_cards[i].dtbo_name); | |
328 | strcat(name_overlays, " "); | |
329 | } | |
330 | ||
331 | /* Apply device tree overlay(s) to the U-Boot environment, if any */ | |
332 | if (strlen(name_overlays)) | |
333 | return env_set("name_overlays", name_overlays); | |
334 | #endif | |
335 | ||
336 | return 0; | |
337 | } | |
338 | ||
339 | int board_late_init(void) | |
340 | { | |
341 | setup_board_eeprom_env(); | |
342 | setup_serial(); | |
343 | ||
344 | /* Check for and probe any plugged-in daughtercards */ | |
345 | probe_daughtercards(); | |
346 | ||
347 | return 0; | |
348 | } | |
349 | ||
350 | void spl_board_init(void) | |
351 | { | |
fa281f64 TK |
352 | #if defined(CONFIG_ESM_K3) || defined(CONFIG_ESM_PMIC) |
353 | struct udevice *dev; | |
354 | int ret; | |
355 | #endif | |
356 | ||
643eb6ea | 357 | probe_daughtercards(); |
fa281f64 TK |
358 | |
359 | #ifdef CONFIG_ESM_K3 | |
360 | if (board_ti_k3_is("J721EX-PM2-SOM")) { | |
361 | ret = uclass_get_device_by_driver(UCLASS_MISC, | |
362 | DM_GET_DRIVER(k3_esm), &dev); | |
363 | if (ret) | |
364 | printf("ESM init failed: %d\n", ret); | |
365 | } | |
366 | #endif | |
367 | ||
368 | #ifdef CONFIG_ESM_PMIC | |
369 | if (board_ti_k3_is("J721EX-PM2-SOM")) { | |
370 | ret = uclass_get_device_by_driver(UCLASS_MISC, | |
371 | DM_GET_DRIVER(pmic_esm), | |
372 | &dev); | |
373 | if (ret) | |
374 | printf("ESM PMIC init failed: %d\n", ret); | |
375 | } | |
376 | #endif | |
643eb6ea | 377 | } |