blob: 88f22e85d731ee0766a0783aabf71cd9579ef317 [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,
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
176 if (get_mc_boot_status() == 0 &&
177 (is_lazy_dpl_addr_valid() || get_dpl_apply_status() == 0))
178 fdt_status_okay(fdt, offset);
179 else
180 fdt_status_fail(fdt, offset);
181}
182
183/* Called after SoC board_late_init in fsl-layerscape/soc.c */
184int fsl_board_late_init(void)
185{
186 ten64_board_retimer_ds110df410_init();
187 return 0;
188}
189
190int ft_board_setup(void *blob, struct bd_info *bd)
191{
192 int i;
193 u16 mc_memory_bank = 0;
194
195 u64 *base;
196 u64 *size;
197 u64 mc_memory_base = 0;
198 u64 mc_memory_size = 0;
199 u16 total_memory_banks;
200
201 debug("%s blob=0x%p\n", __func__, blob);
202
203 ft_cpu_setup(blob, bd);
204
205 fdt_fixup_mc_ddr(&mc_memory_base, &mc_memory_size);
206
207 if (mc_memory_base != 0)
208 mc_memory_bank++;
209
210 total_memory_banks = CONFIG_NR_DRAM_BANKS + mc_memory_bank;
211
212 base = calloc(total_memory_banks, sizeof(u64));
213 size = calloc(total_memory_banks, sizeof(u64));
214
215 /* fixup DT for the two GPP DDR banks */
216 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
217 base[i] = gd->bd->bi_dram[i].start;
218 size[i] = gd->bd->bi_dram[i].size;
219 /* reduce size if reserved memory is within this bank */
Simon Glassb2fb3c62023-02-05 15:40:39 -0700220 if (IS_ENABLED(CONFIG_RESV_RAM) && RESV_MEM_IN_BANK(i))
Mathew McBridee605fb12022-01-31 18:34:43 +0530221 size[i] = gd->arch.resv_ram - base[i];
222 }
223
224 if (mc_memory_base != 0) {
225 for (i = 0; i <= total_memory_banks; i++) {
226 if (base[i] == 0 && size[i] == 0) {
227 base[i] = mc_memory_base;
228 size[i] = mc_memory_size;
229 break;
230 }
231 }
232 }
233
234 fdt_fixup_memory_banks(blob, base, size, total_memory_banks);
235
236 fdt_fsl_mc_fixup_iommu_map_entry(blob);
237
Simon Glass44459d52023-02-05 15:40:01 -0700238 if (IS_ENABLED(CONFIG_FSL_MC_ENET))
Mathew McBridee605fb12022-01-31 18:34:43 +0530239 fdt_fixup_board_enet(blob);
240
241 fdt_fixup_icid(blob);
242
243 return 0;
244}
245
246#define MACADDRBITS(a, b) (u8)(((a) >> (b)) & 0xFF)
247
248/** Probe and return a udevice for the Ten64 board microcontroller.
249 * Optionally, return the I2C bus the microcontroller resides on
250 * @i2c_bus_out: return I2C bus device handle in this pointer
251 */
252static int ten64_get_micro_udevice(struct udevice **ucdev, struct udevice **i2c_bus_out)
253{
254 int ret;
255 struct udevice *i2cbus;
256
257 ret = uclass_get_device_by_seq(UCLASS_I2C, 0, &i2cbus);
258 if (ret) {
259 printf("%s: Could not get I2C UCLASS", __func__);
260 return ret;
261 }
262 if (i2c_bus_out)
263 *i2c_bus_out = i2cbus;
264
265 ret = dm_i2c_probe(i2cbus, 0x7E, DM_I2C_CHIP_RD_ADDRESS, ucdev);
266 if (ret) {
267 printf("%s: Could not get microcontroller device\n", __func__);
268 return ret;
269 }
270 return ret;
271}
272
273static int ten64_read_board_info(struct t64uc_board_info *boardinfo)
274{
275 struct udevice *ucdev;
276 int ret;
277
278 ret = ten64_get_micro_udevice(&ucdev, NULL);
279 if (ret)
280 return ret;
281
282 ret = misc_call(ucdev, TEN64_CNTRL_GET_BOARD_INFO, NULL, 0, (void *)boardinfo, 0);
283 if (ret)
284 return ret;
285
286 return 0;
287}
288
289static void ten64_set_macaddrs_from_board_info(struct t64uc_board_info *boardinfo)
290{
291 char ethaddr[18];
292 char enetvar[10];
293 u8 intfidx, this_dpmac_num;
294 u64 macaddr = 0;
295 /* We will copy the MAC address returned from the
296 * uC (48 bits) into the u64 macaddr
297 */
298 u8 *macaddr_bytes = (u8 *)&macaddr + 2;
299
300 /** MAC addresses are allocated in order of the physical port numbers,
301 * DPMAC7->10 is "eth0" through "eth3"
302 * DPMAC3->6 is "eth4" through "eth7"
303 * DPMAC2 and 1 are "eth8" and "eth9" respectively
304 */
305 int allocation_order[10] = {7, 8, 9, 10, 3, 4, 5, 6, 2, 1};
306
307 memcpy(macaddr_bytes, boardinfo->mac, 6);
308 /* MAC address bytes from uC are in big endian,
309 * convert to CPU
310 */
311 macaddr = __be64_to_cpu(macaddr);
312
313 for (intfidx = 0; intfidx < 10; intfidx++) {
314 snprintf(ethaddr, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
315 MACADDRBITS(macaddr, 40),
316 MACADDRBITS(macaddr, 32),
317 MACADDRBITS(macaddr, 24),
318 MACADDRBITS(macaddr, 16),
319 MACADDRBITS(macaddr, 8),
320 MACADDRBITS(macaddr, 0));
321
322 this_dpmac_num = allocation_order[intfidx];
323 printf("DPMAC%d: %s\n", this_dpmac_num, ethaddr);
324 snprintf(enetvar, 10,
325 (this_dpmac_num != 1) ? "eth%daddr" : "ethaddr",
326 this_dpmac_num - 1);
327 macaddr++;
328
329 if (!env_get(enetvar))
330 env_set(enetvar, ethaddr);
331 }
332}
333
334/* The retimer (DS110DF410) is one of the devices without
335 * a RESET line, but a power switch is on the board
336 * allowing it to be reset via uC command
337 */
338static int board_cycle_retimer(struct udevice **retim_dev)
339{
340 int ret;
341 u8 loop;
342 struct udevice *uc_dev;
343 struct udevice *i2cbus;
344
345 ret = ten64_get_micro_udevice(&uc_dev, &i2cbus);
346 if (ret)
347 return ret;
348
349 ret = dm_i2c_probe(i2cbus, I2C_RETIMER_ADDR, 0, retim_dev);
350 if (ret == 0) {
351 puts("(retimer on, resetting...) ");
352
353 ret = misc_call(uc_dev, TEN64_CNTRL_10G_OFF, NULL, 0, NULL, 0);
354 mdelay(1000);
355 }
356
357 ret = misc_call(uc_dev, TEN64_CNTRL_10G_ON, NULL, 0, NULL, 0);
358
359 // Wait for retimer to come back
360 for (loop = 0; loop < 5; loop++) {
361 ret = dm_i2c_probe(i2cbus, I2C_RETIMER_ADDR, 0, retim_dev);
362 if (ret == 0)
363 return 0;
364 mdelay(500);
365 }
366
367 return -ENOSYS;
368}
369
370/* ten64_board_retimer_ds110df410_init() - Configure the 10G retimer
371 * Adopted from the t102xqds board file
372 */
373static void ten64_board_retimer_ds110df410_init(void)
374{
375 u8 reg;
376 int ret;
377 struct udevice *retim_dev;
378 u32 board_rev = ten64_get_board_rev();
379
380 puts("Retimer: ");
381 /* Retimer power cycle not implemented on early board
382 * revisions/controller firmwares
383 */
Simon Glassf7e33a02023-02-05 17:55:21 -0700384 if (IS_ENABLED(CONFIG_TEN64_CONTROLLER) &&
Mathew McBridee605fb12022-01-31 18:34:43 +0530385 board_rev >= TEN64_BOARD_REV_C) {
386 ret = board_cycle_retimer(&retim_dev);
387 if (ret) {
388 puts("Retimer power on failed\n");
389 return;
390 }
391 }
392
393 /* Access to Control/Shared register */
394 reg = 0x0;
395
396 ret = dm_i2c_write(retim_dev, 0xff, &reg, 1);
397 if (ret) {
398 printf("Error writing to retimer register (error %d)\n", ret);
399 return;
400 }
401
402 /* Read device revision and ID */
403 dm_i2c_read(retim_dev, 1, &reg, 1);
404 if (reg == 0xF0)
405 puts("DS110DF410 found\n");
406 else
407 printf("Unknown retimer 0x%xn\n", reg);
408
409 /* Enable Broadcast */
410 reg = 0x0c;
411 dm_i2c_write(retim_dev, 0xff, &reg, 1);
412
413 /* Perform a full reset (state, channel and clock)
414 * for all channels
415 * as the DS110DF410 does not have a RESET line
416 */
417 dm_i2c_read(retim_dev, 0, &reg, 1);
418 reg |= 0x7;
419 dm_i2c_write(retim_dev, 0, &reg, 1);
420
421 /* Set rate/subrate = 0 */
422 reg = 0x6;
423 dm_i2c_write(retim_dev, 0x2F, &reg, 1);
424
425 /* Set data rate as 10.3125 Gbps */
426 reg = 0x0;
427 dm_i2c_write(retim_dev, 0x60, &reg, 1);
428 reg = 0xb2;
429 dm_i2c_write(retim_dev, 0x61, &reg, 1);
430 reg = 0x90;
431 dm_i2c_write(retim_dev, 0x62, &reg, 1);
432 reg = 0xb3;
433 dm_i2c_write(retim_dev, 0x63, &reg, 1);
434 reg = 0xff;
435 dm_i2c_write(retim_dev, 0x64, &reg, 1);
436
437 /* Invert channel 2 (Lower SFP TX to CPU) due to the SFP being inverted */
438 reg = 0x05;
439 dm_i2c_write(retim_dev, 0xFF, &reg, 1);
440 dm_i2c_read(retim_dev, 0x1F, &reg, 1);
441 reg |= 0x80;
442 dm_i2c_write(retim_dev, 0x1F, &reg, 1);
443
444 puts("OK\n");
445}