blob: d41bd2e9deeb4e330638e8c90546606ef9a96306 [file] [log] [blame]
Mathew McBridee605fb12022-01-31 18:34:43 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Traverse Ten64 Family board
4 * Copyright 2017-2018 NXP
5 * Copyright 2019-2021 Traverse Technologies
6 */
Tom Rinidec7ea02024-05-20 13:35:03 -06007#include <config.h>
Simon Glass1ab16922022-07-31 12:28:48 -06008#include <display_options.h>
Mathew McBridee605fb12022-01-31 18:34:43 +05309#include <dm/uclass.h>
10#include <env.h>
11#include <i2c.h>
12#include <init.h>
13#include <log.h>
14#include <malloc.h>
15#include <errno.h>
16#include <misc.h>
17#include <netdev.h>
18#include <fsl_ifc.h>
19#include <fsl_ddr.h>
20#include <fsl_sec.h>
21#include <asm/global_data.h>
22#include <asm/io.h>
23#include <fdt_support.h>
24#include <linux/delay.h>
25#include <linux/libfdt.h>
26#include <fsl-mc/fsl_mc.h>
27#include <env_internal.h>
28#include <asm/arch-fsl-layerscape/soc.h>
Mathew McBridee605fb12022-01-31 18:34:43 +053029#include <hwconfig.h>
30#include <asm/arch/fsl_serdes.h>
31#include <asm/arch/soc.h>
32#include <asm/arch-fsl-layerscape/fsl_icid.h>
Mathew McBride0710b542023-07-21 04:39:24 +000033#include <nvme.h>
Mathew McBridee605fb12022-01-31 18:34:43 +053034
35#include <fsl_immap.h>
36
37#include "../common/ten64-controller.h"
38
39#define I2C_RETIMER_ADDR 0x27
40
41DECLARE_GLOBAL_DATA_PTR;
42
43static int ten64_read_board_info(struct t64uc_board_info *);
44static void ten64_set_macaddrs_from_board_info(struct t64uc_board_info *);
45static void ten64_board_retimer_ds110df410_init(void);
46
47enum {
48 TEN64_BOARD_REV_A = 0xFF,
49 TEN64_BOARD_REV_B = 0xFE,
Mathew McBride2e4a29e2023-07-21 04:39:16 +000050 TEN64_BOARD_REV_C = 0xFD,
51 TEN64_BOARD_REV_D = 0xFC,
52 TEN64_BOARD_MAX
Mathew McBridee605fb12022-01-31 18:34:43 +053053};
54
55#define RESV_MEM_IN_BANK(b) (gd->arch.resv_ram >= base[b] && \
56 gd->arch.resv_ram < base[b] + size[b])
57
58int board_early_init_f(void)
59{
60 fsl_lsch3_early_init_f();
61 return 0;
62}
63
64static u32 ten64_get_board_rev(void)
65{
Tom Rini376b88a2022-10-28 20:27:13 -040066 struct ccsr_gur *dcfg = (void *)CFG_SYS_FSL_GUTS_ADDR;
Mathew McBridee605fb12022-01-31 18:34:43 +053067 u32 board_rev_in = in_le32(&dcfg->gpporcr1);
68 return board_rev_in;
69}
70
71int checkboard(void)
72{
73 enum boot_src src = get_boot_src();
74 char boardmodel[32];
75 struct t64uc_board_info boardinfo;
76 u32 board_rev = ten64_get_board_rev();
77
78 switch (board_rev) {
79 case TEN64_BOARD_REV_A:
Mathew McBride2e4a29e2023-07-21 04:39:16 +000080 snprintf(boardmodel, 32, "A (Alpha)");
Mathew McBridee605fb12022-01-31 18:34:43 +053081 break;
82 case TEN64_BOARD_REV_B:
Mathew McBride2e4a29e2023-07-21 04:39:16 +000083 snprintf(boardmodel, 32, "B (Beta)");
Mathew McBridee605fb12022-01-31 18:34:43 +053084 break;
85 case TEN64_BOARD_REV_C:
Mathew McBride2e4a29e2023-07-21 04:39:16 +000086 snprintf(boardmodel, 32, "C");
87 break;
88 case TEN64_BOARD_REV_D:
89 snprintf(boardmodel, 32, "D");
Mathew McBridee605fb12022-01-31 18:34:43 +053090 break;
91 default:
Mathew McBride2e4a29e2023-07-21 04:39:16 +000092 snprintf(boardmodel, 32, " Revision %X", (0xFF - board_rev));
Mathew McBridee605fb12022-01-31 18:34:43 +053093 break;
94 }
95
Mathew McBride2e4a29e2023-07-21 04:39:16 +000096 printf("Board: 1064-0201%s, boot from ", boardmodel);
97
Mathew McBridee605fb12022-01-31 18:34:43 +053098 if (src == BOOT_SOURCE_SD_MMC)
99 puts("SD card\n");
100 else if (src == BOOT_SOURCE_QSPI_NOR)
101 puts("QSPI\n");
102 else
103 printf("Unknown boot source %d\n", src);
104
105 puts("Controller: ");
Simon Glassf7e33a02023-02-05 17:55:21 -0700106 if (IS_ENABLED(CONFIG_TEN64_CONTROLLER)) {
Mathew McBridee605fb12022-01-31 18:34:43 +0530107 /* Driver not compatible with alpha/beta board MCU firmware */
108 if (board_rev <= TEN64_BOARD_REV_C) {
109 if (ten64_read_board_info(&boardinfo)) {
110 puts("ERROR: unable to communicate\n");
111 } else {
112 printf("firmware %d.%d.%d\n",
113 boardinfo.fwversion_major,
114 boardinfo.fwversion_minor,
115 boardinfo.fwversion_patch);
116 ten64_set_macaddrs_from_board_info(&boardinfo);
117 }
118 } else {
119 puts("not supported on this board revision\n");
120 }
121 } else {
122 puts("driver not enabled (no MAC addresses or other information will be read)\n");
123 }
124
125 return 0;
126}
127
128int board_init(void)
129{
130 init_final_memctl_regs();
131
Simon Glass8b374d62023-02-05 15:39:59 -0700132 if (IS_ENABLED(CONFIG_FSL_CAAM))
Mathew McBridee605fb12022-01-31 18:34:43 +0530133 sec_init();
134
135 return 0;
136}
137
138int fsl_initdram(void)
139{
140 gd->ram_size = tfa_get_dram_size();
141
142 if (!gd->ram_size)
143 gd->ram_size = fsl_ddr_sdram_size();
144
145 return 0;
146}
147
148void detail_board_ddr_info(void)
149{
150 puts("\nDDR ");
151 print_size(gd->bd->bi_dram[0].size + gd->bd->bi_dram[1].size, "");
152 print_ddr_info(0);
153}
154
155void board_quiesce_devices(void)
156{
157 if (IS_ENABLED(CONFIG_FSL_MC_ENET))
158 fsl_mc_ldpaa_exit(gd->bd);
159}
160
161void fdt_fixup_board_enet(void *fdt)
162{
163 int offset;
164
165 offset = fdt_path_offset(fdt, "/fsl-mc");
166
167 if (offset < 0)
168 offset = fdt_path_offset(fdt, "/soc/fsl-mc");
169
170 if (offset < 0) {
171 printf("%s: ERROR: fsl-mc node not found in device tree (error %d)\n",
172 __func__, offset);
173 return;
174 }
175
Mathew McBride715091b2023-07-21 04:39:31 +0000176 /* In the U-Boot FDT, a 'simple-mfd' compatible is added.
177 * Remove this as FreeBSD will only match "fsl,qoriq-mc"
178 * exactly on the DPAA2 bus/MC node.
179 */
180 fdt_setprop(fdt, offset, "compatible", "fsl,qoriq-mc", 12);
181
Mathew McBridee605fb12022-01-31 18:34:43 +0530182 if (get_mc_boot_status() == 0 &&
183 (is_lazy_dpl_addr_valid() || get_dpl_apply_status() == 0))
184 fdt_status_okay(fdt, offset);
185 else
186 fdt_status_fail(fdt, offset);
187}
188
189/* Called after SoC board_late_init in fsl-layerscape/soc.c */
190int fsl_board_late_init(void)
191{
192 ten64_board_retimer_ds110df410_init();
Mathew McBride0710b542023-07-21 04:39:24 +0000193
194 /* Ensure nvme storage devices are available to bootflow */
195 if (IS_ENABLED(CONFIG_NVME))
196 nvme_scan_namespace();
197
Mathew McBridee605fb12022-01-31 18:34:43 +0530198 return 0;
199}
200
201int ft_board_setup(void *blob, struct bd_info *bd)
202{
203 int i;
204 u16 mc_memory_bank = 0;
205
206 u64 *base;
207 u64 *size;
208 u64 mc_memory_base = 0;
209 u64 mc_memory_size = 0;
210 u16 total_memory_banks;
211
212 debug("%s blob=0x%p\n", __func__, blob);
213
214 ft_cpu_setup(blob, bd);
215
216 fdt_fixup_mc_ddr(&mc_memory_base, &mc_memory_size);
217
218 if (mc_memory_base != 0)
219 mc_memory_bank++;
220
221 total_memory_banks = CONFIG_NR_DRAM_BANKS + mc_memory_bank;
222
223 base = calloc(total_memory_banks, sizeof(u64));
224 size = calloc(total_memory_banks, sizeof(u64));
225
226 /* fixup DT for the two GPP DDR banks */
227 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
228 base[i] = gd->bd->bi_dram[i].start;
229 size[i] = gd->bd->bi_dram[i].size;
230 /* reduce size if reserved memory is within this bank */
Simon Glassb2fb3c62023-02-05 15:40:39 -0700231 if (IS_ENABLED(CONFIG_RESV_RAM) && RESV_MEM_IN_BANK(i))
Mathew McBridee605fb12022-01-31 18:34:43 +0530232 size[i] = gd->arch.resv_ram - base[i];
233 }
234
235 if (mc_memory_base != 0) {
236 for (i = 0; i <= total_memory_banks; i++) {
237 if (base[i] == 0 && size[i] == 0) {
238 base[i] = mc_memory_base;
239 size[i] = mc_memory_size;
240 break;
241 }
242 }
243 }
244
245 fdt_fixup_memory_banks(blob, base, size, total_memory_banks);
246
247 fdt_fsl_mc_fixup_iommu_map_entry(blob);
248
Simon Glass44459d52023-02-05 15:40:01 -0700249 if (IS_ENABLED(CONFIG_FSL_MC_ENET))
Mathew McBridee605fb12022-01-31 18:34:43 +0530250 fdt_fixup_board_enet(blob);
251
252 fdt_fixup_icid(blob);
253
254 return 0;
255}
256
257#define MACADDRBITS(a, b) (u8)(((a) >> (b)) & 0xFF)
258
259/** Probe and return a udevice for the Ten64 board microcontroller.
260 * Optionally, return the I2C bus the microcontroller resides on
261 * @i2c_bus_out: return I2C bus device handle in this pointer
262 */
263static int ten64_get_micro_udevice(struct udevice **ucdev, struct udevice **i2c_bus_out)
264{
265 int ret;
266 struct udevice *i2cbus;
267
268 ret = uclass_get_device_by_seq(UCLASS_I2C, 0, &i2cbus);
269 if (ret) {
270 printf("%s: Could not get I2C UCLASS", __func__);
271 return ret;
272 }
273 if (i2c_bus_out)
274 *i2c_bus_out = i2cbus;
275
276 ret = dm_i2c_probe(i2cbus, 0x7E, DM_I2C_CHIP_RD_ADDRESS, ucdev);
277 if (ret) {
278 printf("%s: Could not get microcontroller device\n", __func__);
279 return ret;
280 }
281 return ret;
282}
283
284static int ten64_read_board_info(struct t64uc_board_info *boardinfo)
285{
286 struct udevice *ucdev;
287 int ret;
288
289 ret = ten64_get_micro_udevice(&ucdev, NULL);
290 if (ret)
291 return ret;
292
293 ret = misc_call(ucdev, TEN64_CNTRL_GET_BOARD_INFO, NULL, 0, (void *)boardinfo, 0);
294 if (ret)
295 return ret;
296
297 return 0;
298}
299
300static void ten64_set_macaddrs_from_board_info(struct t64uc_board_info *boardinfo)
301{
302 char ethaddr[18];
303 char enetvar[10];
Mathew McBridee6cbacf2023-07-21 04:39:26 +0000304 char serial[18];
Mathew McBridee605fb12022-01-31 18:34:43 +0530305 u8 intfidx, this_dpmac_num;
306 u64 macaddr = 0;
307 /* We will copy the MAC address returned from the
308 * uC (48 bits) into the u64 macaddr
309 */
310 u8 *macaddr_bytes = (u8 *)&macaddr + 2;
311
312 /** MAC addresses are allocated in order of the physical port numbers,
313 * DPMAC7->10 is "eth0" through "eth3"
314 * DPMAC3->6 is "eth4" through "eth7"
315 * DPMAC2 and 1 are "eth8" and "eth9" respectively
316 */
317 int allocation_order[10] = {7, 8, 9, 10, 3, 4, 5, 6, 2, 1};
318
319 memcpy(macaddr_bytes, boardinfo->mac, 6);
320 /* MAC address bytes from uC are in big endian,
321 * convert to CPU
322 */
323 macaddr = __be64_to_cpu(macaddr);
324
Mathew McBridee6cbacf2023-07-21 04:39:26 +0000325 /* Set serial# to GE0/DPMAC7 MAC address
326 * (Matches the labels on the board and appliance)
327 */
328 snprintf(serial, 18, "%02X%02X%02X%02X%02X%02X",
329 MACADDRBITS(macaddr, 40),
330 MACADDRBITS(macaddr, 32),
331 MACADDRBITS(macaddr, 24),
332 MACADDRBITS(macaddr, 16),
333 MACADDRBITS(macaddr, 8),
334 MACADDRBITS(macaddr, 0));
335 if (!env_get("serial#"))
336 env_set("serial#", serial);
337
Mathew McBridee605fb12022-01-31 18:34:43 +0530338 for (intfidx = 0; intfidx < 10; intfidx++) {
339 snprintf(ethaddr, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
340 MACADDRBITS(macaddr, 40),
341 MACADDRBITS(macaddr, 32),
342 MACADDRBITS(macaddr, 24),
343 MACADDRBITS(macaddr, 16),
344 MACADDRBITS(macaddr, 8),
345 MACADDRBITS(macaddr, 0));
346
347 this_dpmac_num = allocation_order[intfidx];
348 printf("DPMAC%d: %s\n", this_dpmac_num, ethaddr);
349 snprintf(enetvar, 10,
Mathew McBride24b0ab02023-07-21 04:39:25 +0000350 (intfidx != 0) ? "eth%daddr" : "ethaddr",
351 intfidx);
Mathew McBridee605fb12022-01-31 18:34:43 +0530352 macaddr++;
353
354 if (!env_get(enetvar))
355 env_set(enetvar, ethaddr);
356 }
357}
358
359/* The retimer (DS110DF410) is one of the devices without
360 * a RESET line, but a power switch is on the board
361 * allowing it to be reset via uC command
362 */
363static int board_cycle_retimer(struct udevice **retim_dev)
364{
365 int ret;
366 u8 loop;
367 struct udevice *uc_dev;
368 struct udevice *i2cbus;
Mathew McBride22879432023-07-21 04:39:17 +0000369 u32 board_rev = ten64_get_board_rev();
Mathew McBridee605fb12022-01-31 18:34:43 +0530370
371 ret = ten64_get_micro_udevice(&uc_dev, &i2cbus);
372 if (ret)
373 return ret;
374
Mathew McBride22879432023-07-21 04:39:17 +0000375 /* Retimer power cycle not implemented on early board
376 * revisions/controller firmwares
377 */
378 if (IS_ENABLED(CONFIG_TEN64_CONTROLLER) &&
379 board_rev <= TEN64_BOARD_REV_C) {
380 ret = dm_i2c_probe(i2cbus, I2C_RETIMER_ADDR, 0, retim_dev);
381 if (ret == 0) {
382 puts("(retimer on, resetting...) ");
Mathew McBridee605fb12022-01-31 18:34:43 +0530383
Mathew McBride22879432023-07-21 04:39:17 +0000384 ret = misc_call(uc_dev, TEN64_CNTRL_10G_OFF, NULL, 0, NULL, 0);
Mathew McBrideed378402023-08-07 01:41:08 +0000385 if (ret)
386 return ret;
Mathew McBride22879432023-07-21 04:39:17 +0000387 mdelay(1000);
388 }
Mathew McBridee605fb12022-01-31 18:34:43 +0530389
Mathew McBrideed378402023-08-07 01:41:08 +0000390 /* Turn on the retimer */
Mathew McBride22879432023-07-21 04:39:17 +0000391 ret = misc_call(uc_dev, TEN64_CNTRL_10G_ON, NULL, 0, NULL, 0);
Mathew McBrideed378402023-08-07 01:41:08 +0000392 if (ret)
393 return ret;
Mathew McBride22879432023-07-21 04:39:17 +0000394 }
Mathew McBridee605fb12022-01-31 18:34:43 +0530395
396 // Wait for retimer to come back
397 for (loop = 0; loop < 5; loop++) {
398 ret = dm_i2c_probe(i2cbus, I2C_RETIMER_ADDR, 0, retim_dev);
399 if (ret == 0)
400 return 0;
401 mdelay(500);
402 }
403
404 return -ENOSYS;
405}
406
407/* ten64_board_retimer_ds110df410_init() - Configure the 10G retimer
408 * Adopted from the t102xqds board file
409 */
410static void ten64_board_retimer_ds110df410_init(void)
411{
412 u8 reg;
413 int ret;
414 struct udevice *retim_dev;
Mathew McBridee605fb12022-01-31 18:34:43 +0530415
416 puts("Retimer: ");
Mathew McBride22879432023-07-21 04:39:17 +0000417
418 ret = board_cycle_retimer(&retim_dev);
419 if (ret) {
420 puts("Retimer power on failed\n");
421 return;
Mathew McBridee605fb12022-01-31 18:34:43 +0530422 }
423
424 /* Access to Control/Shared register */
425 reg = 0x0;
426
427 ret = dm_i2c_write(retim_dev, 0xff, &reg, 1);
428 if (ret) {
429 printf("Error writing to retimer register (error %d)\n", ret);
430 return;
431 }
432
433 /* Read device revision and ID */
434 dm_i2c_read(retim_dev, 1, &reg, 1);
435 if (reg == 0xF0)
436 puts("DS110DF410 found\n");
437 else
438 printf("Unknown retimer 0x%xn\n", reg);
439
440 /* Enable Broadcast */
441 reg = 0x0c;
442 dm_i2c_write(retim_dev, 0xff, &reg, 1);
443
444 /* Perform a full reset (state, channel and clock)
445 * for all channels
446 * as the DS110DF410 does not have a RESET line
447 */
448 dm_i2c_read(retim_dev, 0, &reg, 1);
449 reg |= 0x7;
450 dm_i2c_write(retim_dev, 0, &reg, 1);
451
452 /* Set rate/subrate = 0 */
453 reg = 0x6;
454 dm_i2c_write(retim_dev, 0x2F, &reg, 1);
455
456 /* Set data rate as 10.3125 Gbps */
457 reg = 0x0;
458 dm_i2c_write(retim_dev, 0x60, &reg, 1);
459 reg = 0xb2;
460 dm_i2c_write(retim_dev, 0x61, &reg, 1);
461 reg = 0x90;
462 dm_i2c_write(retim_dev, 0x62, &reg, 1);
463 reg = 0xb3;
464 dm_i2c_write(retim_dev, 0x63, &reg, 1);
465 reg = 0xff;
466 dm_i2c_write(retim_dev, 0x64, &reg, 1);
467
468 /* Invert channel 2 (Lower SFP TX to CPU) due to the SFP being inverted */
469 reg = 0x05;
470 dm_i2c_write(retim_dev, 0xFF, &reg, 1);
471 dm_i2c_read(retim_dev, 0x1F, &reg, 1);
472 reg |= 0x80;
473 dm_i2c_write(retim_dev, 0x1F, &reg, 1);
474
475 puts("OK\n");
476}
Mathew McBride0710b542023-07-21 04:39:24 +0000477
Mathew McBride9f55a3d2023-07-21 04:39:30 +0000478/* Opt out of the fsl_setenv_bootcmd
479 * in arch/arm/cpu/armv8/fsl-layerscape/soc.c
480 * which is invoked by board_late_init.
481 */
482int fsl_setenv_bootcmd(void)
483{
484 return 0;
485}
486