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