blob: 0febc0baf0393128d85485733929984b3177a528 [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 */
7#include <common.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>
29#include <asm/arch/ppa.h>
30#include <hwconfig.h>
31#include <asm/arch/fsl_serdes.h>
32#include <asm/arch/soc.h>
33#include <asm/arch-fsl-layerscape/fsl_icid.h>
Mathew McBride0710b542023-07-21 04:39:24 +000034#include <nvme.h>
Mathew McBridee605fb12022-01-31 18:34:43 +053035
36#include <fsl_immap.h>
37
38#include "../common/ten64-controller.h"
39
40#define I2C_RETIMER_ADDR 0x27
41
42DECLARE_GLOBAL_DATA_PTR;
43
44static int ten64_read_board_info(struct t64uc_board_info *);
45static void ten64_set_macaddrs_from_board_info(struct t64uc_board_info *);
46static void ten64_board_retimer_ds110df410_init(void);
47
48enum {
49 TEN64_BOARD_REV_A = 0xFF,
50 TEN64_BOARD_REV_B = 0xFE,
Mathew McBride2e4a29e2023-07-21 04:39:16 +000051 TEN64_BOARD_REV_C = 0xFD,
52 TEN64_BOARD_REV_D = 0xFC,
53 TEN64_BOARD_MAX
Mathew McBridee605fb12022-01-31 18:34:43 +053054};
55
56#define RESV_MEM_IN_BANK(b) (gd->arch.resv_ram >= base[b] && \
57 gd->arch.resv_ram < base[b] + size[b])
58
59int board_early_init_f(void)
60{
61 fsl_lsch3_early_init_f();
62 return 0;
63}
64
65static u32 ten64_get_board_rev(void)
66{
Tom Rini376b88a2022-10-28 20:27:13 -040067 struct ccsr_gur *dcfg = (void *)CFG_SYS_FSL_GUTS_ADDR;
Mathew McBridee605fb12022-01-31 18:34:43 +053068 u32 board_rev_in = in_le32(&dcfg->gpporcr1);
69 return board_rev_in;
70}
71
72int checkboard(void)
73{
74 enum boot_src src = get_boot_src();
75 char boardmodel[32];
76 struct t64uc_board_info boardinfo;
77 u32 board_rev = ten64_get_board_rev();
78
79 switch (board_rev) {
80 case TEN64_BOARD_REV_A:
Mathew McBride2e4a29e2023-07-21 04:39:16 +000081 snprintf(boardmodel, 32, "A (Alpha)");
Mathew McBridee605fb12022-01-31 18:34:43 +053082 break;
83 case TEN64_BOARD_REV_B:
Mathew McBride2e4a29e2023-07-21 04:39:16 +000084 snprintf(boardmodel, 32, "B (Beta)");
Mathew McBridee605fb12022-01-31 18:34:43 +053085 break;
86 case TEN64_BOARD_REV_C:
Mathew McBride2e4a29e2023-07-21 04:39:16 +000087 snprintf(boardmodel, 32, "C");
88 break;
89 case TEN64_BOARD_REV_D:
90 snprintf(boardmodel, 32, "D");
Mathew McBridee605fb12022-01-31 18:34:43 +053091 break;
92 default:
Mathew McBride2e4a29e2023-07-21 04:39:16 +000093 snprintf(boardmodel, 32, " Revision %X", (0xFF - board_rev));
Mathew McBridee605fb12022-01-31 18:34:43 +053094 break;
95 }
96
Mathew McBride2e4a29e2023-07-21 04:39:16 +000097 printf("Board: 1064-0201%s, boot from ", boardmodel);
98
Mathew McBridee605fb12022-01-31 18:34:43 +053099 if (src == BOOT_SOURCE_SD_MMC)
100 puts("SD card\n");
101 else if (src == BOOT_SOURCE_QSPI_NOR)
102 puts("QSPI\n");
103 else
104 printf("Unknown boot source %d\n", src);
105
106 puts("Controller: ");
Simon Glassf7e33a02023-02-05 17:55:21 -0700107 if (IS_ENABLED(CONFIG_TEN64_CONTROLLER)) {
Mathew McBridee605fb12022-01-31 18:34:43 +0530108 /* Driver not compatible with alpha/beta board MCU firmware */
109 if (board_rev <= TEN64_BOARD_REV_C) {
110 if (ten64_read_board_info(&boardinfo)) {
111 puts("ERROR: unable to communicate\n");
112 } else {
113 printf("firmware %d.%d.%d\n",
114 boardinfo.fwversion_major,
115 boardinfo.fwversion_minor,
116 boardinfo.fwversion_patch);
117 ten64_set_macaddrs_from_board_info(&boardinfo);
118 }
119 } else {
120 puts("not supported on this board revision\n");
121 }
122 } else {
123 puts("driver not enabled (no MAC addresses or other information will be read)\n");
124 }
125
126 return 0;
127}
128
129int board_init(void)
130{
131 init_final_memctl_regs();
132
Simon Glass8b374d62023-02-05 15:39:59 -0700133 if (IS_ENABLED(CONFIG_FSL_CAAM))
Mathew McBridee605fb12022-01-31 18:34:43 +0530134 sec_init();
135
136 return 0;
137}
138
139int fsl_initdram(void)
140{
141 gd->ram_size = tfa_get_dram_size();
142
143 if (!gd->ram_size)
144 gd->ram_size = fsl_ddr_sdram_size();
145
146 return 0;
147}
148
149void detail_board_ddr_info(void)
150{
151 puts("\nDDR ");
152 print_size(gd->bd->bi_dram[0].size + gd->bd->bi_dram[1].size, "");
153 print_ddr_info(0);
154}
155
156void board_quiesce_devices(void)
157{
158 if (IS_ENABLED(CONFIG_FSL_MC_ENET))
159 fsl_mc_ldpaa_exit(gd->bd);
160}
161
162void fdt_fixup_board_enet(void *fdt)
163{
164 int offset;
165
166 offset = fdt_path_offset(fdt, "/fsl-mc");
167
168 if (offset < 0)
169 offset = fdt_path_offset(fdt, "/soc/fsl-mc");
170
171 if (offset < 0) {
172 printf("%s: ERROR: fsl-mc node not found in device tree (error %d)\n",
173 __func__, offset);
174 return;
175 }
176
177 if (get_mc_boot_status() == 0 &&
178 (is_lazy_dpl_addr_valid() || get_dpl_apply_status() == 0))
179 fdt_status_okay(fdt, offset);
180 else
181 fdt_status_fail(fdt, offset);
182}
183
184/* Called after SoC board_late_init in fsl-layerscape/soc.c */
185int fsl_board_late_init(void)
186{
187 ten64_board_retimer_ds110df410_init();
Mathew McBride0710b542023-07-21 04:39:24 +0000188
189 /* Ensure nvme storage devices are available to bootflow */
190 if (IS_ENABLED(CONFIG_NVME))
191 nvme_scan_namespace();
192
Mathew McBridee605fb12022-01-31 18:34:43 +0530193 return 0;
194}
195
196int ft_board_setup(void *blob, struct bd_info *bd)
197{
198 int i;
199 u16 mc_memory_bank = 0;
200
201 u64 *base;
202 u64 *size;
203 u64 mc_memory_base = 0;
204 u64 mc_memory_size = 0;
205 u16 total_memory_banks;
206
207 debug("%s blob=0x%p\n", __func__, blob);
208
209 ft_cpu_setup(blob, bd);
210
211 fdt_fixup_mc_ddr(&mc_memory_base, &mc_memory_size);
212
213 if (mc_memory_base != 0)
214 mc_memory_bank++;
215
216 total_memory_banks = CONFIG_NR_DRAM_BANKS + mc_memory_bank;
217
218 base = calloc(total_memory_banks, sizeof(u64));
219 size = calloc(total_memory_banks, sizeof(u64));
220
221 /* fixup DT for the two GPP DDR banks */
222 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
223 base[i] = gd->bd->bi_dram[i].start;
224 size[i] = gd->bd->bi_dram[i].size;
225 /* reduce size if reserved memory is within this bank */
Simon Glassb2fb3c62023-02-05 15:40:39 -0700226 if (IS_ENABLED(CONFIG_RESV_RAM) && RESV_MEM_IN_BANK(i))
Mathew McBridee605fb12022-01-31 18:34:43 +0530227 size[i] = gd->arch.resv_ram - base[i];
228 }
229
230 if (mc_memory_base != 0) {
231 for (i = 0; i <= total_memory_banks; i++) {
232 if (base[i] == 0 && size[i] == 0) {
233 base[i] = mc_memory_base;
234 size[i] = mc_memory_size;
235 break;
236 }
237 }
238 }
239
240 fdt_fixup_memory_banks(blob, base, size, total_memory_banks);
241
242 fdt_fsl_mc_fixup_iommu_map_entry(blob);
243
Simon Glass44459d52023-02-05 15:40:01 -0700244 if (IS_ENABLED(CONFIG_FSL_MC_ENET))
Mathew McBridee605fb12022-01-31 18:34:43 +0530245 fdt_fixup_board_enet(blob);
246
247 fdt_fixup_icid(blob);
248
249 return 0;
250}
251
252#define MACADDRBITS(a, b) (u8)(((a) >> (b)) & 0xFF)
253
254/** Probe and return a udevice for the Ten64 board microcontroller.
255 * Optionally, return the I2C bus the microcontroller resides on
256 * @i2c_bus_out: return I2C bus device handle in this pointer
257 */
258static int ten64_get_micro_udevice(struct udevice **ucdev, struct udevice **i2c_bus_out)
259{
260 int ret;
261 struct udevice *i2cbus;
262
263 ret = uclass_get_device_by_seq(UCLASS_I2C, 0, &i2cbus);
264 if (ret) {
265 printf("%s: Could not get I2C UCLASS", __func__);
266 return ret;
267 }
268 if (i2c_bus_out)
269 *i2c_bus_out = i2cbus;
270
271 ret = dm_i2c_probe(i2cbus, 0x7E, DM_I2C_CHIP_RD_ADDRESS, ucdev);
272 if (ret) {
273 printf("%s: Could not get microcontroller device\n", __func__);
274 return ret;
275 }
276 return ret;
277}
278
279static int ten64_read_board_info(struct t64uc_board_info *boardinfo)
280{
281 struct udevice *ucdev;
282 int ret;
283
284 ret = ten64_get_micro_udevice(&ucdev, NULL);
285 if (ret)
286 return ret;
287
288 ret = misc_call(ucdev, TEN64_CNTRL_GET_BOARD_INFO, NULL, 0, (void *)boardinfo, 0);
289 if (ret)
290 return ret;
291
292 return 0;
293}
294
295static void ten64_set_macaddrs_from_board_info(struct t64uc_board_info *boardinfo)
296{
297 char ethaddr[18];
298 char enetvar[10];
299 u8 intfidx, this_dpmac_num;
300 u64 macaddr = 0;
301 /* We will copy the MAC address returned from the
302 * uC (48 bits) into the u64 macaddr
303 */
304 u8 *macaddr_bytes = (u8 *)&macaddr + 2;
305
306 /** MAC addresses are allocated in order of the physical port numbers,
307 * DPMAC7->10 is "eth0" through "eth3"
308 * DPMAC3->6 is "eth4" through "eth7"
309 * DPMAC2 and 1 are "eth8" and "eth9" respectively
310 */
311 int allocation_order[10] = {7, 8, 9, 10, 3, 4, 5, 6, 2, 1};
312
313 memcpy(macaddr_bytes, boardinfo->mac, 6);
314 /* MAC address bytes from uC are in big endian,
315 * convert to CPU
316 */
317 macaddr = __be64_to_cpu(macaddr);
318
319 for (intfidx = 0; intfidx < 10; intfidx++) {
320 snprintf(ethaddr, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
321 MACADDRBITS(macaddr, 40),
322 MACADDRBITS(macaddr, 32),
323 MACADDRBITS(macaddr, 24),
324 MACADDRBITS(macaddr, 16),
325 MACADDRBITS(macaddr, 8),
326 MACADDRBITS(macaddr, 0));
327
328 this_dpmac_num = allocation_order[intfidx];
329 printf("DPMAC%d: %s\n", this_dpmac_num, ethaddr);
330 snprintf(enetvar, 10,
Mathew McBride24b0ab02023-07-21 04:39:25 +0000331 (intfidx != 0) ? "eth%daddr" : "ethaddr",
332 intfidx);
Mathew McBridee605fb12022-01-31 18:34:43 +0530333 macaddr++;
334
335 if (!env_get(enetvar))
336 env_set(enetvar, ethaddr);
337 }
338}
339
340/* The retimer (DS110DF410) is one of the devices without
341 * a RESET line, but a power switch is on the board
342 * allowing it to be reset via uC command
343 */
344static int board_cycle_retimer(struct udevice **retim_dev)
345{
346 int ret;
347 u8 loop;
348 struct udevice *uc_dev;
349 struct udevice *i2cbus;
Mathew McBride22879432023-07-21 04:39:17 +0000350 u32 board_rev = ten64_get_board_rev();
Mathew McBridee605fb12022-01-31 18:34:43 +0530351
352 ret = ten64_get_micro_udevice(&uc_dev, &i2cbus);
353 if (ret)
354 return ret;
355
Mathew McBride22879432023-07-21 04:39:17 +0000356 /* Retimer power cycle not implemented on early board
357 * revisions/controller firmwares
358 */
359 if (IS_ENABLED(CONFIG_TEN64_CONTROLLER) &&
360 board_rev <= TEN64_BOARD_REV_C) {
361 ret = dm_i2c_probe(i2cbus, I2C_RETIMER_ADDR, 0, retim_dev);
362 if (ret == 0) {
363 puts("(retimer on, resetting...) ");
Mathew McBridee605fb12022-01-31 18:34:43 +0530364
Mathew McBride22879432023-07-21 04:39:17 +0000365 ret = misc_call(uc_dev, TEN64_CNTRL_10G_OFF, NULL, 0, NULL, 0);
366 mdelay(1000);
367 }
Mathew McBridee605fb12022-01-31 18:34:43 +0530368
Mathew McBride22879432023-07-21 04:39:17 +0000369 ret = misc_call(uc_dev, TEN64_CNTRL_10G_ON, NULL, 0, NULL, 0);
370 }
Mathew McBridee605fb12022-01-31 18:34:43 +0530371
372 // Wait for retimer to come back
373 for (loop = 0; loop < 5; loop++) {
374 ret = dm_i2c_probe(i2cbus, I2C_RETIMER_ADDR, 0, retim_dev);
375 if (ret == 0)
376 return 0;
377 mdelay(500);
378 }
379
380 return -ENOSYS;
381}
382
383/* ten64_board_retimer_ds110df410_init() - Configure the 10G retimer
384 * Adopted from the t102xqds board file
385 */
386static void ten64_board_retimer_ds110df410_init(void)
387{
388 u8 reg;
389 int ret;
390 struct udevice *retim_dev;
Mathew McBridee605fb12022-01-31 18:34:43 +0530391
392 puts("Retimer: ");
Mathew McBride22879432023-07-21 04:39:17 +0000393
394 ret = board_cycle_retimer(&retim_dev);
395 if (ret) {
396 puts("Retimer power on failed\n");
397 return;
Mathew McBridee605fb12022-01-31 18:34:43 +0530398 }
399
400 /* Access to Control/Shared register */
401 reg = 0x0;
402
403 ret = dm_i2c_write(retim_dev, 0xff, &reg, 1);
404 if (ret) {
405 printf("Error writing to retimer register (error %d)\n", ret);
406 return;
407 }
408
409 /* Read device revision and ID */
410 dm_i2c_read(retim_dev, 1, &reg, 1);
411 if (reg == 0xF0)
412 puts("DS110DF410 found\n");
413 else
414 printf("Unknown retimer 0x%xn\n", reg);
415
416 /* Enable Broadcast */
417 reg = 0x0c;
418 dm_i2c_write(retim_dev, 0xff, &reg, 1);
419
420 /* Perform a full reset (state, channel and clock)
421 * for all channels
422 * as the DS110DF410 does not have a RESET line
423 */
424 dm_i2c_read(retim_dev, 0, &reg, 1);
425 reg |= 0x7;
426 dm_i2c_write(retim_dev, 0, &reg, 1);
427
428 /* Set rate/subrate = 0 */
429 reg = 0x6;
430 dm_i2c_write(retim_dev, 0x2F, &reg, 1);
431
432 /* Set data rate as 10.3125 Gbps */
433 reg = 0x0;
434 dm_i2c_write(retim_dev, 0x60, &reg, 1);
435 reg = 0xb2;
436 dm_i2c_write(retim_dev, 0x61, &reg, 1);
437 reg = 0x90;
438 dm_i2c_write(retim_dev, 0x62, &reg, 1);
439 reg = 0xb3;
440 dm_i2c_write(retim_dev, 0x63, &reg, 1);
441 reg = 0xff;
442 dm_i2c_write(retim_dev, 0x64, &reg, 1);
443
444 /* Invert channel 2 (Lower SFP TX to CPU) due to the SFP being inverted */
445 reg = 0x05;
446 dm_i2c_write(retim_dev, 0xFF, &reg, 1);
447 dm_i2c_read(retim_dev, 0x1F, &reg, 1);
448 reg |= 0x80;
449 dm_i2c_write(retim_dev, 0x1F, &reg, 1);
450
451 puts("OK\n");
452}
Mathew McBride0710b542023-07-21 04:39:24 +0000453