]>
Commit | Line | Data |
---|---|---|
0911d952 LV |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Board specific initialization for AM654 EVM | |
4 | * | |
5 | * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ | |
6 | * Lokesh Vutla <[email protected]> | |
7 | * | |
8 | */ | |
9 | ||
10 | #include <common.h> | |
03facc72 | 11 | #include <dm.h> |
67c4e9f8 | 12 | #include <init.h> |
90526e9f | 13 | #include <net.h> |
03facc72 AD |
14 | #include <asm/arch/sys_proto.h> |
15 | #include <asm/arch/hardware.h> | |
16 | #include <asm/gpio.h> | |
0911d952 | 17 | #include <asm/io.h> |
03facc72 | 18 | #include <asm/omap_common.h> |
9fb625ce | 19 | #include <env.h> |
0911d952 | 20 | #include <spl.h> |
5582c035 | 21 | #include <asm/arch/sys_proto.h> |
0911d952 | 22 | |
03facc72 AD |
23 | #include "../common/board_detect.h" |
24 | ||
25 | #define board_is_am65x_base_board() board_ti_is("AM6-COMPROCEVM") | |
26 | ||
27 | /* Daughter card presence detection signals */ | |
28 | enum { | |
29 | AM65X_EVM_APP_BRD_DET, | |
30 | AM65X_EVM_LCD_BRD_DET, | |
31 | AM65X_EVM_SERDES_BRD_DET, | |
32 | AM65X_EVM_HDMI_GPMC_BRD_DET, | |
33 | AM65X_EVM_BRD_DET_COUNT, | |
34 | }; | |
35 | ||
36 | /* Max number of MAC addresses that are parsed/processed per daughter card */ | |
37 | #define DAUGHTER_CARD_NO_OF_MAC_ADDR 8 | |
38 | ||
0911d952 LV |
39 | DECLARE_GLOBAL_DATA_PTR; |
40 | ||
41 | int board_init(void) | |
42 | { | |
43 | return 0; | |
44 | } | |
45 | ||
46 | int dram_init(void) | |
47 | { | |
48 | #ifdef CONFIG_PHYS_64BIT | |
49 | gd->ram_size = 0x100000000; | |
50 | #else | |
51 | gd->ram_size = 0x80000000; | |
52 | #endif | |
53 | ||
54 | return 0; | |
55 | } | |
56 | ||
57 | ulong board_get_usable_ram_top(ulong total_size) | |
58 | { | |
59 | #ifdef CONFIG_PHYS_64BIT | |
60 | /* Limit RAM used by U-Boot to the DDR low region */ | |
61 | if (gd->ram_top > 0x100000000) | |
62 | return 0x100000000; | |
63 | #endif | |
64 | ||
65 | return gd->ram_top; | |
66 | } | |
67 | ||
68 | int dram_init_banksize(void) | |
69 | { | |
70 | /* Bank 0 declares the memory available in the DDR low region */ | |
71 | gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; | |
72 | gd->bd->bi_dram[0].size = 0x80000000; | |
73 | ||
74 | #ifdef CONFIG_PHYS_64BIT | |
75 | /* Bank 1 declares the memory available in the DDR high region */ | |
76 | gd->bd->bi_dram[1].start = CONFIG_SYS_SDRAM_BASE1; | |
77 | gd->bd->bi_dram[1].size = 0x80000000; | |
78 | #endif | |
79 | ||
80 | return 0; | |
81 | } | |
ea8ad1d9 LV |
82 | |
83 | #ifdef CONFIG_SPL_LOAD_FIT | |
84 | int board_fit_config_name_match(const char *name) | |
85 | { | |
86 | #ifdef CONFIG_TARGET_AM654_A53_EVM | |
87 | if (!strcmp(name, "k3-am654-base-board")) | |
88 | return 0; | |
89 | #endif | |
90 | ||
91 | return -1; | |
92 | } | |
93 | #endif | |
5582c035 LV |
94 | |
95 | #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) | |
96 | int ft_board_setup(void *blob, bd_t *bd) | |
97 | { | |
98 | int ret; | |
99 | ||
100 | ret = fdt_fixup_msmc_ram(blob, "/interconnect@100000", "sram@70000000"); | |
29c9db4d | 101 | if (ret) { |
5582c035 | 102 | printf("%s: fixing up msmc ram failed %d\n", __func__, ret); |
29c9db4d AD |
103 | return ret; |
104 | } | |
105 | ||
106 | #if defined(CONFIG_TI_SECURE_DEVICE) | |
107 | /* Make HW RNG reserved for secure world use */ | |
108 | ret = fdt_disable_node(blob, "/interconnect@100000/trng@4e10000"); | |
28b90a46 | 109 | if (ret) |
29c9db4d | 110 | printf("%s: disabling TRGN failed %d\n", __func__, ret); |
29c9db4d | 111 | #endif |
5582c035 | 112 | |
29c9db4d | 113 | return 0; |
5582c035 LV |
114 | } |
115 | #endif | |
03facc72 AD |
116 | |
117 | int do_board_detect(void) | |
118 | { | |
119 | int ret; | |
120 | ||
121 | ret = ti_i2c_eeprom_am6_get_base(CONFIG_EEPROM_BUS_ADDRESS, | |
122 | CONFIG_EEPROM_CHIP_ADDRESS); | |
123 | if (ret) | |
124 | pr_err("Reading on-board EEPROM at 0x%02x failed %d\n", | |
125 | CONFIG_EEPROM_CHIP_ADDRESS, ret); | |
126 | ||
127 | return ret; | |
128 | } | |
129 | ||
bd8f138f LV |
130 | int checkboard(void) |
131 | { | |
132 | struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; | |
133 | ||
134 | if (do_board_detect()) | |
135 | /* EEPROM not populated */ | |
136 | printf("Board: %s rev %s\n", "AM6-COMPROCEVM", "E3"); | |
137 | else | |
138 | printf("Board: %s rev %s\n", ep->name, ep->version); | |
139 | ||
140 | return 0; | |
141 | } | |
142 | ||
03facc72 AD |
143 | static void setup_board_eeprom_env(void) |
144 | { | |
145 | char *name = "am65x"; | |
146 | ||
147 | if (do_board_detect()) | |
148 | goto invalid_eeprom; | |
149 | ||
150 | if (board_is_am65x_base_board()) | |
151 | name = "am65x"; | |
152 | else | |
153 | printf("Unidentified board claims %s in eeprom header\n", | |
154 | board_ti_get_name()); | |
155 | ||
156 | invalid_eeprom: | |
157 | set_board_info_env_am6(name); | |
158 | } | |
159 | ||
160 | static int init_daughtercard_det_gpio(char *gpio_name, struct gpio_desc *desc) | |
161 | { | |
162 | int ret; | |
163 | ||
164 | memset(desc, 0, sizeof(*desc)); | |
165 | ||
166 | ret = dm_gpio_lookup_name(gpio_name, desc); | |
167 | if (ret < 0) | |
168 | return ret; | |
169 | ||
170 | /* Request GPIO, simply re-using the name as label */ | |
171 | ret = dm_gpio_request(desc, gpio_name); | |
172 | if (ret < 0) | |
173 | return ret; | |
174 | ||
175 | return dm_gpio_set_dir_flags(desc, GPIOD_IS_IN); | |
176 | } | |
177 | ||
178 | static int probe_daughtercards(void) | |
179 | { | |
180 | struct ti_am6_eeprom ep; | |
181 | struct gpio_desc board_det_gpios[AM65X_EVM_BRD_DET_COUNT]; | |
182 | char mac_addr[DAUGHTER_CARD_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN]; | |
183 | u8 mac_addr_cnt; | |
184 | char name_overlays[1024] = { 0 }; | |
185 | int i, j; | |
186 | int ret; | |
187 | ||
188 | /* | |
189 | * Daughter card presence detection signal name to GPIO (via I2C I/O | |
190 | * expander @ address 0x38) name and EEPROM I2C address mapping. | |
191 | */ | |
192 | const struct { | |
193 | char *gpio_name; | |
194 | u8 i2c_addr; | |
195 | } slot_map[AM65X_EVM_BRD_DET_COUNT] = { | |
196 | { "gpio@38_0", 0x52, }, /* AM65X_EVM_APP_BRD_DET */ | |
197 | { "gpio@38_1", 0x55, }, /* AM65X_EVM_LCD_BRD_DET */ | |
198 | { "gpio@38_2", 0x54, }, /* AM65X_EVM_SERDES_BRD_DET */ | |
199 | { "gpio@38_3", 0x53, }, /* AM65X_EVM_HDMI_GPMC_BRD_DET */ | |
200 | }; | |
201 | ||
202 | /* Declaration of daughtercards to probe */ | |
203 | const struct { | |
204 | u8 slot_index; /* Slot the card is installed */ | |
205 | char *card_name; /* EEPROM-programmed card name */ | |
206 | char *dtbo_name; /* Device tree overlay to apply */ | |
207 | u8 eth_offset; /* ethXaddr MAC address index offset */ | |
208 | } cards[] = { | |
209 | { | |
210 | AM65X_EVM_APP_BRD_DET, | |
211 | "AM6-GPAPPEVM", | |
212 | "k3-am654-gp.dtbo", | |
213 | 0, | |
214 | }, | |
215 | { | |
216 | AM65X_EVM_APP_BRD_DET, | |
217 | "AM6-IDKAPPEVM", | |
218 | "k3-am654-idk.dtbo", | |
219 | 3, | |
220 | }, | |
221 | { | |
222 | AM65X_EVM_SERDES_BRD_DET, | |
223 | "SER-PCIE2LEVM", | |
224 | "k3-am654-pcie-usb2.dtbo", | |
225 | 0, | |
226 | }, | |
227 | { | |
228 | AM65X_EVM_SERDES_BRD_DET, | |
229 | "SER-PCIEUSBEVM", | |
230 | "k3-am654-pcie-usb3.dtbo", | |
231 | 0, | |
232 | }, | |
233 | { | |
234 | AM65X_EVM_LCD_BRD_DET, | |
235 | "OLDI-LCD1EVM", | |
236 | "k3-am654-evm-oldi-lcd1evm.dtbo", | |
237 | 0, | |
238 | }, | |
239 | }; | |
240 | ||
241 | /* | |
242 | * Initialize GPIO used for daughtercard slot presence detection and | |
243 | * keep the resulting handles in local array for easier access. | |
244 | */ | |
245 | for (i = 0; i < AM65X_EVM_BRD_DET_COUNT; i++) { | |
246 | ret = init_daughtercard_det_gpio(slot_map[i].gpio_name, | |
247 | &board_det_gpios[i]); | |
248 | if (ret < 0) | |
249 | return ret; | |
250 | } | |
251 | ||
252 | for (i = 0; i < ARRAY_SIZE(cards); i++) { | |
253 | /* Obtain card-specific slot index and associated I2C address */ | |
254 | u8 slot_index = cards[i].slot_index; | |
255 | u8 i2c_addr = slot_map[slot_index].i2c_addr; | |
256 | ||
257 | /* | |
258 | * The presence detection signal is active-low, hence skip | |
259 | * over this card slot if anything other than 0 is returned. | |
260 | */ | |
261 | ret = dm_gpio_get_value(&board_det_gpios[slot_index]); | |
262 | if (ret < 0) | |
263 | return ret; | |
264 | else if (ret) | |
265 | continue; | |
266 | ||
267 | /* Get and parse the daughter card EEPROM record */ | |
268 | ret = ti_i2c_eeprom_am6_get(CONFIG_EEPROM_BUS_ADDRESS, i2c_addr, | |
269 | &ep, | |
270 | (char **)mac_addr, | |
271 | DAUGHTER_CARD_NO_OF_MAC_ADDR, | |
272 | &mac_addr_cnt); | |
273 | if (ret) { | |
274 | pr_err("Reading daughtercard EEPROM at 0x%02x failed %d\n", | |
275 | i2c_addr, ret); | |
276 | /* | |
277 | * Even this is pretty serious let's just skip over | |
278 | * this particular daughtercard, rather than ending | |
279 | * the probing process altogether. | |
280 | */ | |
281 | continue; | |
282 | } | |
283 | ||
284 | /* Only process the parsed data if we found a match */ | |
285 | if (strncmp(ep.name, cards[i].card_name, sizeof(ep.name))) | |
286 | continue; | |
287 | ||
bd8f138f | 288 | printf("Detected: %s rev %s\n", ep.name, ep.version); |
03facc72 AD |
289 | |
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 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 | cards[i].eth_offset + j, | |
302 | (uchar *)mac_addr[j]); | |
303 | } | |
304 | ||
305 | /* Skip if no overlays are to be added */ | |
306 | if (!strlen(cards[i].dtbo_name)) | |
307 | continue; | |
308 | ||
309 | /* | |
310 | * Make sure we are not running out of buffer space by checking | |
311 | * if we can fit the new overlay, a trailing space to be used | |
312 | * as a separator, plus the terminating zero. | |
313 | */ | |
314 | if (strlen(name_overlays) + strlen(cards[i].dtbo_name) + 2 > | |
315 | sizeof(name_overlays)) | |
316 | return -ENOMEM; | |
317 | ||
318 | /* Append to our list of overlays */ | |
319 | strcat(name_overlays, cards[i].dtbo_name); | |
320 | strcat(name_overlays, " "); | |
321 | } | |
322 | ||
323 | /* Apply device tree overlay(s) to the U-Boot environment, if any */ | |
324 | if (strlen(name_overlays)) | |
325 | return env_set("name_overlays", name_overlays); | |
326 | ||
327 | return 0; | |
328 | } | |
329 | ||
330 | int board_late_init(void) | |
331 | { | |
332 | struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; | |
333 | ||
334 | setup_board_eeprom_env(); | |
335 | ||
336 | /* | |
337 | * The first MAC address for ethernet a.k.a. ethernet0 comes from | |
338 | * efuse populated via the am654 gigabit eth switch subsystem driver. | |
339 | * All the other ones are populated via EEPROM, hence continue with | |
340 | * an index of 1. | |
341 | */ | |
342 | board_ti_am6_set_ethaddr(1, ep->mac_addr_cnt); | |
343 | ||
344 | /* Check for and probe any plugged-in daughtercards */ | |
345 | probe_daughtercards(); | |
346 | ||
347 | return 0; | |
348 | } |