"...fsl-layerscape/arch/arm/cpu/armv8/fsl-layerscape/fdt.c" did not exist on "c4fddedc48f336eabc4ce3f74940e6aa372de18c"
fdt.c 13.6 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0+
2
/*
3
 * Copyright 2014-2015 Freescale Semiconductor, Inc.
4
 * Copyright 2020 NXP
5
6
7
 */

#include <common.h>
8
#include <clock_legacy.h>
9
#include <efi_loader.h>
10
#include <log.h>
11
#include <asm/cache.h>
12
#include <linux/libfdt.h>
13
#include <fdt_support.h>
14
15
16
17
#include <phy.h>
#ifdef CONFIG_FSL_LSCH3
#include <asm/arch/fdt.h>
#endif
18
19
20
#ifdef CONFIG_FSL_ESDHC
#include <fsl_esdhc.h>
#endif
21
22
23
#ifdef CONFIG_SYS_DPAA_FMAN
#include <fsl_fman.h>
#endif
24
25
26
#ifdef CONFIG_MP
#include <asm/arch/mp.h>
#endif
27
28
#include <fsl_sec.h>
#include <asm/arch-fsl-layerscape/soc.h>
29
30
31
#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
#include <asm/armv8/sec_firmware.h>
#endif
32
33
#include <asm/arch/speed.h>
#include <fsl_qbman.h>
34

Shaohui Xie's avatar
Shaohui Xie committed
35
36
int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc)
{
37
38
39
40
41
42
43
44
	const char *conn;

	/* Do NOT apply fixup for backplane modes specified in DT */
	if (phyc == PHY_INTERFACE_MODE_XGMII) {
		conn = fdt_getprop(blob, offset, "phy-connection-type", NULL);
		if (is_backplane_mode(conn))
			return 0;
	}
Shaohui Xie's avatar
Shaohui Xie committed
45
46
47
48
	return fdt_setprop_string(blob, offset, "phy-connection-type",
					 phy_string_for_interface(phyc));
}

49
50
51
52
53
54
55
#ifdef CONFIG_MP
void ft_fixup_cpu(void *blob)
{
	int off;
	__maybe_unused u64 spin_tbl_addr = (u64)get_spin_tbl_addr();
	fdt32_t *reg;
	int addr_cells;
56
	u64 val, core_id;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
	u32 mask = cpu_pos_mask();
	int off_prev = -1;

	off = fdt_path_offset(blob, "/cpus");
	if (off < 0) {
		puts("couldn't find /cpus node\n");
		return;
	}

	fdt_support_default_count_cells(blob, off, &addr_cells, NULL);

	off = fdt_node_offset_by_prop_value(blob, off_prev, "device_type",
					    "cpu", 4);
	while (off != -FDT_ERR_NOTFOUND) {
		reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0);
		if (reg) {
			core_id = fdt_read_number(reg, addr_cells);
			if (!test_bit(id_to_core(core_id), &mask)) {
				fdt_del_node(blob, off);
				off = off_prev;
			}
		}
		off_prev = off;
		off = fdt_node_offset_by_prop_value(blob, off_prev,
						    "device_type", "cpu", 4);
	}

84
#if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) && \
85
	defined(CONFIG_SEC_FIRMWARE_ARMV8_PSCI)
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	int node;
	u32 psci_ver;

	/* Check the psci version to determine if the psci is supported */
	psci_ver = sec_firmware_support_psci_version();
	if (psci_ver == 0xffffffff) {
		/* remove psci DT node */
		node = fdt_path_offset(blob, "/psci");
		if (node >= 0)
			goto remove_psci_node;

		node = fdt_node_offset_by_compatible(blob, -1, "arm,psci");
		if (node >= 0)
			goto remove_psci_node;

		node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-0.2");
		if (node >= 0)
			goto remove_psci_node;
104

105
106
107
108
109
110
111
112
113
114
115
		node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-1.0");
		if (node >= 0)
			goto remove_psci_node;

remove_psci_node:
		if (node >= 0)
			fdt_del_node(blob, node);
	} else {
		return;
	}
#endif
116
117
118
119
120
	off = fdt_path_offset(blob, "/cpus");
	if (off < 0) {
		puts("couldn't find /cpus node\n");
		return;
	}
121
	fdt_support_default_count_cells(blob, off, &addr_cells, NULL);
122
123
124
125
126

	off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
	while (off != -FDT_ERR_NOTFOUND) {
		reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0);
		if (reg) {
127
			core_id = fdt_read_number(reg, addr_cells);
128
129
130
131
132
133
134
135
136
137
138
139
			if (core_id  == 0 || (is_core_online(core_id))) {
				val = spin_tbl_addr;
				val += id_to_core(core_id) *
				       SPIN_TABLE_ELEM_SIZE;
				val = cpu_to_fdt64(val);
				fdt_setprop_string(blob, off, "enable-method",
						   "spin-table");
				fdt_setprop(blob, off, "cpu-release-addr",
					    &val, sizeof(val));
			} else {
				debug("skipping offline core\n");
			}
140
141
142
143
144
145
146
		} else {
			puts("Warning: found cpu node without reg property\n");
		}
		off = fdt_node_offset_by_prop_value(blob, off, "device_type",
						    "cpu", 4);
	}

147
148
	fdt_add_mem_rsv(blob, (uintptr_t)secondary_boot_code_start,
			secondary_boot_code_size);
Stephen Warren's avatar
Stephen Warren committed
149
#if CONFIG_IS_ENABLED(EFI_LOADER)
150
151
	efi_add_memory_map((uintptr_t)secondary_boot_code_start,
			   secondary_boot_code_size, EFI_RESERVED_MEMORY_TYPE);
152
#endif
153
154
155
}
#endif

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
void fsl_fdt_disable_usb(void *blob)
{
	int off;
	/*
	 * SYSCLK is used as a reference clock for USB. When the USB
	 * controller is used, SYSCLK must meet the additional requirement
	 * of 100 MHz.
	 */
	if (CONFIG_SYS_CLK_FREQ != 100000000) {
		off = fdt_node_offset_by_compatible(blob, -1, "snps,dwc3");
		while (off != -FDT_ERR_NOTFOUND) {
			fdt_status_disabled(blob, off);
			off = fdt_node_offset_by_compatible(blob, off,
							    "snps,dwc3");
		}
	}
}

174
175
176
177
178
179
180
181
182
183
184
185
#ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN
static void fdt_fixup_gic(void *blob)
{
	int offset, err;
	u64 reg[8];
	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
	unsigned int val;
	struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
	int align_64k = 0;

	val = gur_in32(&gur->svr);

186
	if (!IS_SVR_DEV(val, SVR_DEV(SVR_LS1043A))) {
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
		align_64k = 1;
	} else if (SVR_REV(val) != REV1_0) {
		val = scfg_in32(&scfg->gic_align) & (0x01 << GIC_ADDR_BIT);
		if (!val)
			align_64k = 1;
	}

	offset = fdt_subnode_offset(blob, 0, "interrupt-controller@1400000");
	if (offset < 0) {
		printf("WARNING: fdt_subnode_offset can't find node %s: %s\n",
		       "interrupt-controller@1400000", fdt_strerror(offset));
		return;
	}

	/* Fixup gic node align with 64K */
	if (align_64k) {
		reg[0] = cpu_to_fdt64(GICD_BASE_64K);
		reg[1] = cpu_to_fdt64(GICD_SIZE_64K);
		reg[2] = cpu_to_fdt64(GICC_BASE_64K);
		reg[3] = cpu_to_fdt64(GICC_SIZE_64K);
		reg[4] = cpu_to_fdt64(GICH_BASE_64K);
		reg[5] = cpu_to_fdt64(GICH_SIZE_64K);
		reg[6] = cpu_to_fdt64(GICV_BASE_64K);
		reg[7] = cpu_to_fdt64(GICV_SIZE_64K);
	} else {
	/* Fixup gic node align with default */
		reg[0] = cpu_to_fdt64(GICD_BASE);
		reg[1] = cpu_to_fdt64(GICD_SIZE);
		reg[2] = cpu_to_fdt64(GICC_BASE);
		reg[3] = cpu_to_fdt64(GICC_SIZE);
		reg[4] = cpu_to_fdt64(GICH_BASE);
		reg[5] = cpu_to_fdt64(GICH_SIZE);
		reg[6] = cpu_to_fdt64(GICV_BASE);
		reg[7] = cpu_to_fdt64(GICV_SIZE);
	}

	err = fdt_setprop(blob, offset, "reg", reg, sizeof(reg));
	if (err < 0) {
		printf("WARNING: fdt_setprop can't set %s from node %s: %s\n",
		       "reg", "interrupt-controller@1400000",
		       fdt_strerror(err));
		return;
	}

	return;
}
#endif

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
#ifdef CONFIG_HAS_FEATURE_ENHANCED_MSI
static int _fdt_fixup_msi_node(void *blob, const char *name,
				  int irq_0, int irq_1, int rev)
{
	int err, offset, len;
	u32 tmp[4][3];
	void *p;

	offset = fdt_path_offset(blob, name);
	if (offset < 0) {
		printf("WARNING: fdt_path_offset can't find path %s: %s\n",
		       name, fdt_strerror(offset));
		return 0;
	}

	/*fixup the property of interrupts*/

	tmp[0][0] = cpu_to_fdt32(0x0);
	tmp[0][1] = cpu_to_fdt32(irq_0);
	tmp[0][2] = cpu_to_fdt32(0x4);

	if (rev > REV1_0) {
		tmp[1][0] = cpu_to_fdt32(0x0);
		tmp[1][1] = cpu_to_fdt32(irq_1);
		tmp[1][2] = cpu_to_fdt32(0x4);
		tmp[2][0] = cpu_to_fdt32(0x0);
		tmp[2][1] = cpu_to_fdt32(irq_1 + 1);
		tmp[2][2] = cpu_to_fdt32(0x4);
		tmp[3][0] = cpu_to_fdt32(0x0);
		tmp[3][1] = cpu_to_fdt32(irq_1 + 2);
		tmp[3][2] = cpu_to_fdt32(0x4);
		len = sizeof(tmp);
	} else {
		len = sizeof(tmp[0]);
	}

	err = fdt_setprop(blob, offset, "interrupts", tmp, len);
	if (err < 0) {
		printf("WARNING: fdt_setprop can't set %s from node %s: %s\n",
		       "interrupts", name, fdt_strerror(err));
		return 0;
	}

	/*fixup the property of reg*/
	p = (char *)fdt_getprop(blob, offset, "reg", &len);
	if (!p) {
		printf("WARNING: fdt_getprop can't get %s from node %s\n",
		       "reg", name);
		return 0;
	}

	memcpy((char *)tmp, p, len);

	if (rev > REV1_0)
		*((u32 *)tmp + 3) = cpu_to_fdt32(0x1000);
	else
		*((u32 *)tmp + 3) = cpu_to_fdt32(0x8);

	err = fdt_setprop(blob, offset, "reg", tmp, len);
	if (err < 0) {
		printf("WARNING: fdt_setprop can't set %s from node %s: %s\n",
		       "reg", name, fdt_strerror(err));
		return 0;
	}

	/*fixup the property of compatible*/
	if (rev > REV1_0)
		err = fdt_setprop_string(blob, offset, "compatible",
					 "fsl,ls1043a-v1.1-msi");
	else
		err = fdt_setprop_string(blob, offset, "compatible",
					 "fsl,ls1043a-msi");
	if (err < 0) {
		printf("WARNING: fdt_setprop can't set %s from node %s: %s\n",
		       "compatible", name, fdt_strerror(err));
		return 0;
	}

	return 1;
}

static int _fdt_fixup_pci_msi(void *blob, const char *name, int rev)
{
	int offset, len, err;
	void *p;
	int val;
	u32 tmp[4][8];

	offset = fdt_path_offset(blob, name);
	if (offset < 0) {
		printf("WARNING: fdt_path_offset can't find path %s: %s\n",
		       name, fdt_strerror(offset));
		return 0;
	}

	p = (char *)fdt_getprop(blob, offset, "interrupt-map", &len);
	if (!p || len != sizeof(tmp)) {
		printf("WARNING: fdt_getprop can't get %s from node %s\n",
		       "interrupt-map", name);
		return 0;
	}

	memcpy((char *)tmp, p, len);

	val = fdt32_to_cpu(tmp[0][6]);
340
	if (rev == REV1_0) {
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
		tmp[1][6] = cpu_to_fdt32(val + 1);
		tmp[2][6] = cpu_to_fdt32(val + 2);
		tmp[3][6] = cpu_to_fdt32(val + 3);
	} else {
		tmp[1][6] = cpu_to_fdt32(val);
		tmp[2][6] = cpu_to_fdt32(val);
		tmp[3][6] = cpu_to_fdt32(val);
	}

	err = fdt_setprop(blob, offset, "interrupt-map", tmp, sizeof(tmp));
	if (err < 0) {
		printf("WARNING: fdt_setprop can't set %s from node %s: %s.\n",
		       "interrupt-map", name, fdt_strerror(err));
		return 0;
	}
	return 1;
}

/* Fixup msi node for ls1043a rev1.1*/

static void fdt_fixup_msi(void *blob)
{
	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
	unsigned int rev;

	rev = gur_in32(&gur->svr);

368
	if (!IS_SVR_DEV(rev, SVR_DEV(SVR_LS1043A)))
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
		return;

	rev = SVR_REV(rev);

	_fdt_fixup_msi_node(blob, "/soc/msi-controller1@1571000",
			    116, 111, rev);
	_fdt_fixup_msi_node(blob, "/soc/msi-controller2@1572000",
			    126, 121, rev);
	_fdt_fixup_msi_node(blob, "/soc/msi-controller3@1573000",
			    160, 155, rev);

	_fdt_fixup_pci_msi(blob, "/soc/pcie@3400000", rev);
	_fdt_fixup_pci_msi(blob, "/soc/pcie@3500000", rev);
	_fdt_fixup_pci_msi(blob, "/soc/pcie@3600000", rev);
}
#endif

386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
/* Remove JR node used by SEC firmware */
void fdt_fixup_remove_jr(void *blob)
{
	int jr_node, addr_cells, len;
	int crypto_node = fdt_path_offset(blob, "crypto");
	u64 jr_offset, used_jr;
	fdt32_t *reg;

	used_jr = sec_firmware_used_jobring_offset();
	fdt_support_default_count_cells(blob, crypto_node, &addr_cells, NULL);

	jr_node = fdt_node_offset_by_compatible(blob, crypto_node,
						"fsl,sec-v4.0-job-ring");

	while (jr_node != -FDT_ERR_NOTFOUND) {
		reg = (fdt32_t *)fdt_getprop(blob, jr_node, "reg", &len);
403
404
405
406
407
408
		if (reg) {
			jr_offset = fdt_read_number(reg, addr_cells);
			if (jr_offset == used_jr) {
				fdt_del_node(blob, jr_node);
				break;
			}
409
410
411
412
413
414
415
		}
		jr_node = fdt_node_offset_by_compatible(blob, jr_node,
							"fsl,sec-v4.0-job-ring");
	}
}
#endif

416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
#ifdef CONFIG_ARCH_LS1028A
static void fdt_disable_multimedia(void *blob, unsigned int svr)
{
	int off;

	if (IS_MULTIMEDIA_EN(svr))
		return;

	/* Disable eDP/LCD node */
	off = fdt_node_offset_by_compatible(blob, -1, "arm,mali-dp500");
	if (off != -FDT_ERR_NOTFOUND)
		fdt_status_disabled(blob, off);

	/* Disable GPU node */
	off = fdt_node_offset_by_compatible(blob, -1, "fsl,ls1028a-gpu");
	if (off != -FDT_ERR_NOTFOUND)
		fdt_status_disabled(blob, off);
}
#endif

436
437
438
439
440
441
#ifdef CONFIG_PCIE_ECAM_GENERIC
__weak void fdt_fixup_ecam(void *blob)
{
}
#endif

442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
/*
 * If it is a non-E part the crypto is disabled on the following SoCs:
 *  - LS1043A
 *  - LS1088A
 *  - LS2080A
 *  - LS2088A
 * and their personalities.
 *
 * On all other SoCs just the export-controlled ciphers are disabled, that
 * means that the following is still working:
 *  - hashing (using MDHA - message digest hash accelerator)
 *  - random number generation (using RNG4)
 *  - cyclic redundancy checking (using CRCA)
 *  - runtime integrity checker (RTIC)
 *
 * The linux driver will figure out what is available and what is not.
 * Therefore, we just remove the crypto node on the SoCs which have no crypto
 * support at all.
 */
static bool crypto_is_disabled(unsigned int svr)
{
	if (IS_E_PROCESSOR(svr))
		return false;

	if (IS_SVR_DEV(svr, SVR_DEV(SVR_LS1043A)))
		return true;

	if (IS_SVR_DEV(svr, SVR_DEV(SVR_LS1088A)))
		return true;

	if (IS_SVR_DEV(svr, SVR_DEV(SVR_LS2080A)))
		return true;

	if (IS_SVR_DEV(svr, SVR_DEV(SVR_LS2088A)))
		return true;

	return false;
}

481
void ft_cpu_setup(void *blob, struct bd_info *bd)
482
{
483
	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
484
	unsigned int svr = gur_in32(&gur->svr);
485
486

	/* delete crypto node if not on an E-processor */
487
	if (crypto_is_disabled(svr))
488
489
490
491
492
		fdt_fixup_crypto_node(blob, 0);
#if CONFIG_SYS_FSL_SEC_COMPAT >= 4
	else {
		ccsr_sec_t __iomem *sec;

493
#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
494
495
		fdt_fixup_remove_jr(blob);
		fdt_fixup_kaslr(blob);
496
497
#endif

498
499
500
501
502
		sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
		fdt_fixup_crypto_node(blob, sec_in32(&sec->secvid_ms));
	}
#endif

503
504
505
#ifdef CONFIG_MP
	ft_fixup_cpu(blob);
#endif
506
507

#ifdef CONFIG_SYS_NS16550
508
	do_fixup_by_compat_u32(blob, "fsl,ns16550",
509
510
			       "clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
#endif
511

512
513
	do_fixup_by_path_u32(blob, "/sysclk", "clock-frequency",
			     CONFIG_SYS_CLK_FREQ, 1);
514

515
516
517
518
#ifdef CONFIG_GIC_V3_ITS
	ls_gic_rd_tables_init(blob);
#endif

519
#if defined(CONFIG_PCIE_LAYERSCAPE) || defined(CONFIG_PCIE_LAYERSCAPE_GEN4)
520
521
522
	ft_pci_setup(blob, bd);
#endif

523
#ifdef CONFIG_FSL_ESDHC
524
525
	fdt_fixup_esdhc(blob, bd);
#endif
526

527
528
529
530
531
532
533
#ifdef CONFIG_SYS_DPAA_QBMAN
	fdt_fixup_bportals(blob);
	fdt_fixup_qportals(blob);
	do_fixup_by_compat_u32(blob, "fsl,qman",
			       "clock-frequency", get_qman_freq(), 1);
#endif

534
535
536
#ifdef CONFIG_SYS_DPAA_FMAN
	fdt_fixup_fman_firmware(blob);
#endif
537
#ifndef CONFIG_ARCH_LS1012A
538
	fsl_fdt_disable_usb(blob);
539
#endif
540
541
542
#ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN
	fdt_fixup_gic(blob);
#endif
543
544
545
#ifdef CONFIG_HAS_FEATURE_ENHANCED_MSI
	fdt_fixup_msi(blob);
#endif
546
547
548
#ifdef CONFIG_ARCH_LS1028A
	fdt_disable_multimedia(blob, svr);
#endif
549
550
551
#ifdef CONFIG_PCIE_ECAM_GENERIC
	fdt_fixup_ecam(blob);
#endif
552
}