1 /* 2 * Copyright 2014-2015 Freescale Semiconductor, Inc. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <efi_loader.h> 9 #include <linux/libfdt.h> 10 #include <fdt_support.h> 11 #include <phy.h> 12 #ifdef CONFIG_FSL_LSCH3 13 #include <asm/arch/fdt.h> 14 #endif 15 #ifdef CONFIG_FSL_ESDHC 16 #include <fsl_esdhc.h> 17 #endif 18 #ifdef CONFIG_SYS_DPAA_FMAN 19 #include <fsl_fman.h> 20 #endif 21 #ifdef CONFIG_MP 22 #include <asm/arch/mp.h> 23 #endif 24 #include <fsl_sec.h> 25 #include <asm/arch-fsl-layerscape/soc.h> 26 #ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT 27 #include <asm/armv8/sec_firmware.h> 28 #endif 29 #include <asm/arch/speed.h> 30 #include <fsl_qbman.h> 31 32 int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc) 33 { 34 return fdt_setprop_string(blob, offset, "phy-connection-type", 35 phy_string_for_interface(phyc)); 36 } 37 38 #ifdef CONFIG_MP 39 void ft_fixup_cpu(void *blob) 40 { 41 int off; 42 __maybe_unused u64 spin_tbl_addr = (u64)get_spin_tbl_addr(); 43 fdt32_t *reg; 44 int addr_cells; 45 u64 val, core_id; 46 size_t *boot_code_size = &(__secondary_boot_code_size); 47 u32 mask = cpu_pos_mask(); 48 int off_prev = -1; 49 50 off = fdt_path_offset(blob, "/cpus"); 51 if (off < 0) { 52 puts("couldn't find /cpus node\n"); 53 return; 54 } 55 56 fdt_support_default_count_cells(blob, off, &addr_cells, NULL); 57 58 off = fdt_node_offset_by_prop_value(blob, off_prev, "device_type", 59 "cpu", 4); 60 while (off != -FDT_ERR_NOTFOUND) { 61 reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0); 62 if (reg) { 63 core_id = fdt_read_number(reg, addr_cells); 64 if (!test_bit(id_to_core(core_id), &mask)) { 65 fdt_del_node(blob, off); 66 off = off_prev; 67 } 68 } 69 off_prev = off; 70 off = fdt_node_offset_by_prop_value(blob, off_prev, 71 "device_type", "cpu", 4); 72 } 73 74 #if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) && \ 75 defined(CONFIG_SEC_FIRMWARE_ARMV8_PSCI) 76 int node; 77 u32 psci_ver; 78 79 /* Check the psci version to determine if the psci is supported */ 80 psci_ver = sec_firmware_support_psci_version(); 81 if (psci_ver == 0xffffffff) { 82 /* remove psci DT node */ 83 node = fdt_path_offset(blob, "/psci"); 84 if (node >= 0) 85 goto remove_psci_node; 86 87 node = fdt_node_offset_by_compatible(blob, -1, "arm,psci"); 88 if (node >= 0) 89 goto remove_psci_node; 90 91 node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-0.2"); 92 if (node >= 0) 93 goto remove_psci_node; 94 95 node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-1.0"); 96 if (node >= 0) 97 goto remove_psci_node; 98 99 remove_psci_node: 100 if (node >= 0) 101 fdt_del_node(blob, node); 102 } else { 103 return; 104 } 105 #endif 106 off = fdt_path_offset(blob, "/cpus"); 107 if (off < 0) { 108 puts("couldn't find /cpus node\n"); 109 return; 110 } 111 fdt_support_default_count_cells(blob, off, &addr_cells, NULL); 112 113 off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); 114 while (off != -FDT_ERR_NOTFOUND) { 115 reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0); 116 if (reg) { 117 core_id = fdt_read_number(reg, addr_cells); 118 if (core_id == 0 || (is_core_online(core_id))) { 119 val = spin_tbl_addr; 120 val += id_to_core(core_id) * 121 SPIN_TABLE_ELEM_SIZE; 122 val = cpu_to_fdt64(val); 123 fdt_setprop_string(blob, off, "enable-method", 124 "spin-table"); 125 fdt_setprop(blob, off, "cpu-release-addr", 126 &val, sizeof(val)); 127 } else { 128 debug("skipping offline core\n"); 129 } 130 } else { 131 puts("Warning: found cpu node without reg property\n"); 132 } 133 off = fdt_node_offset_by_prop_value(blob, off, "device_type", 134 "cpu", 4); 135 } 136 137 fdt_add_mem_rsv(blob, (uintptr_t)&secondary_boot_code, 138 *boot_code_size); 139 #if defined(CONFIG_EFI_LOADER) && !defined(CONFIG_SPL_BUILD) 140 efi_add_memory_map((uintptr_t)&secondary_boot_code, 141 ALIGN(*boot_code_size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT, 142 EFI_RESERVED_MEMORY_TYPE, false); 143 #endif 144 } 145 #endif 146 147 void fsl_fdt_disable_usb(void *blob) 148 { 149 int off; 150 /* 151 * SYSCLK is used as a reference clock for USB. When the USB 152 * controller is used, SYSCLK must meet the additional requirement 153 * of 100 MHz. 154 */ 155 if (CONFIG_SYS_CLK_FREQ != 100000000) { 156 off = fdt_node_offset_by_compatible(blob, -1, "snps,dwc3"); 157 while (off != -FDT_ERR_NOTFOUND) { 158 fdt_status_disabled(blob, off); 159 off = fdt_node_offset_by_compatible(blob, off, 160 "snps,dwc3"); 161 } 162 } 163 } 164 165 #ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN 166 static void fdt_fixup_gic(void *blob) 167 { 168 int offset, err; 169 u64 reg[8]; 170 struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); 171 unsigned int val; 172 struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR; 173 int align_64k = 0; 174 175 val = gur_in32(&gur->svr); 176 177 if (!IS_SVR_DEV(val, SVR_DEV(SVR_LS1043A))) { 178 align_64k = 1; 179 } else if (SVR_REV(val) != REV1_0) { 180 val = scfg_in32(&scfg->gic_align) & (0x01 << GIC_ADDR_BIT); 181 if (!val) 182 align_64k = 1; 183 } 184 185 offset = fdt_subnode_offset(blob, 0, "interrupt-controller@1400000"); 186 if (offset < 0) { 187 printf("WARNING: fdt_subnode_offset can't find node %s: %s\n", 188 "interrupt-controller@1400000", fdt_strerror(offset)); 189 return; 190 } 191 192 /* Fixup gic node align with 64K */ 193 if (align_64k) { 194 reg[0] = cpu_to_fdt64(GICD_BASE_64K); 195 reg[1] = cpu_to_fdt64(GICD_SIZE_64K); 196 reg[2] = cpu_to_fdt64(GICC_BASE_64K); 197 reg[3] = cpu_to_fdt64(GICC_SIZE_64K); 198 reg[4] = cpu_to_fdt64(GICH_BASE_64K); 199 reg[5] = cpu_to_fdt64(GICH_SIZE_64K); 200 reg[6] = cpu_to_fdt64(GICV_BASE_64K); 201 reg[7] = cpu_to_fdt64(GICV_SIZE_64K); 202 } else { 203 /* Fixup gic node align with default */ 204 reg[0] = cpu_to_fdt64(GICD_BASE); 205 reg[1] = cpu_to_fdt64(GICD_SIZE); 206 reg[2] = cpu_to_fdt64(GICC_BASE); 207 reg[3] = cpu_to_fdt64(GICC_SIZE); 208 reg[4] = cpu_to_fdt64(GICH_BASE); 209 reg[5] = cpu_to_fdt64(GICH_SIZE); 210 reg[6] = cpu_to_fdt64(GICV_BASE); 211 reg[7] = cpu_to_fdt64(GICV_SIZE); 212 } 213 214 err = fdt_setprop(blob, offset, "reg", reg, sizeof(reg)); 215 if (err < 0) { 216 printf("WARNING: fdt_setprop can't set %s from node %s: %s\n", 217 "reg", "interrupt-controller@1400000", 218 fdt_strerror(err)); 219 return; 220 } 221 222 return; 223 } 224 #endif 225 226 #ifdef CONFIG_HAS_FEATURE_ENHANCED_MSI 227 static int _fdt_fixup_msi_node(void *blob, const char *name, 228 int irq_0, int irq_1, int rev) 229 { 230 int err, offset, len; 231 u32 tmp[4][3]; 232 void *p; 233 234 offset = fdt_path_offset(blob, name); 235 if (offset < 0) { 236 printf("WARNING: fdt_path_offset can't find path %s: %s\n", 237 name, fdt_strerror(offset)); 238 return 0; 239 } 240 241 /*fixup the property of interrupts*/ 242 243 tmp[0][0] = cpu_to_fdt32(0x0); 244 tmp[0][1] = cpu_to_fdt32(irq_0); 245 tmp[0][2] = cpu_to_fdt32(0x4); 246 247 if (rev > REV1_0) { 248 tmp[1][0] = cpu_to_fdt32(0x0); 249 tmp[1][1] = cpu_to_fdt32(irq_1); 250 tmp[1][2] = cpu_to_fdt32(0x4); 251 tmp[2][0] = cpu_to_fdt32(0x0); 252 tmp[2][1] = cpu_to_fdt32(irq_1 + 1); 253 tmp[2][2] = cpu_to_fdt32(0x4); 254 tmp[3][0] = cpu_to_fdt32(0x0); 255 tmp[3][1] = cpu_to_fdt32(irq_1 + 2); 256 tmp[3][2] = cpu_to_fdt32(0x4); 257 len = sizeof(tmp); 258 } else { 259 len = sizeof(tmp[0]); 260 } 261 262 err = fdt_setprop(blob, offset, "interrupts", tmp, len); 263 if (err < 0) { 264 printf("WARNING: fdt_setprop can't set %s from node %s: %s\n", 265 "interrupts", name, fdt_strerror(err)); 266 return 0; 267 } 268 269 /*fixup the property of reg*/ 270 p = (char *)fdt_getprop(blob, offset, "reg", &len); 271 if (!p) { 272 printf("WARNING: fdt_getprop can't get %s from node %s\n", 273 "reg", name); 274 return 0; 275 } 276 277 memcpy((char *)tmp, p, len); 278 279 if (rev > REV1_0) 280 *((u32 *)tmp + 3) = cpu_to_fdt32(0x1000); 281 else 282 *((u32 *)tmp + 3) = cpu_to_fdt32(0x8); 283 284 err = fdt_setprop(blob, offset, "reg", tmp, len); 285 if (err < 0) { 286 printf("WARNING: fdt_setprop can't set %s from node %s: %s\n", 287 "reg", name, fdt_strerror(err)); 288 return 0; 289 } 290 291 /*fixup the property of compatible*/ 292 if (rev > REV1_0) 293 err = fdt_setprop_string(blob, offset, "compatible", 294 "fsl,ls1043a-v1.1-msi"); 295 else 296 err = fdt_setprop_string(blob, offset, "compatible", 297 "fsl,ls1043a-msi"); 298 if (err < 0) { 299 printf("WARNING: fdt_setprop can't set %s from node %s: %s\n", 300 "compatible", name, fdt_strerror(err)); 301 return 0; 302 } 303 304 return 1; 305 } 306 307 static int _fdt_fixup_pci_msi(void *blob, const char *name, int rev) 308 { 309 int offset, len, err; 310 void *p; 311 int val; 312 u32 tmp[4][8]; 313 314 offset = fdt_path_offset(blob, name); 315 if (offset < 0) { 316 printf("WARNING: fdt_path_offset can't find path %s: %s\n", 317 name, fdt_strerror(offset)); 318 return 0; 319 } 320 321 p = (char *)fdt_getprop(blob, offset, "interrupt-map", &len); 322 if (!p || len != sizeof(tmp)) { 323 printf("WARNING: fdt_getprop can't get %s from node %s\n", 324 "interrupt-map", name); 325 return 0; 326 } 327 328 memcpy((char *)tmp, p, len); 329 330 val = fdt32_to_cpu(tmp[0][6]); 331 if (rev > REV1_0) { 332 tmp[1][6] = cpu_to_fdt32(val + 1); 333 tmp[2][6] = cpu_to_fdt32(val + 2); 334 tmp[3][6] = cpu_to_fdt32(val + 3); 335 } else { 336 tmp[1][6] = cpu_to_fdt32(val); 337 tmp[2][6] = cpu_to_fdt32(val); 338 tmp[3][6] = cpu_to_fdt32(val); 339 } 340 341 err = fdt_setprop(blob, offset, "interrupt-map", tmp, sizeof(tmp)); 342 if (err < 0) { 343 printf("WARNING: fdt_setprop can't set %s from node %s: %s.\n", 344 "interrupt-map", name, fdt_strerror(err)); 345 return 0; 346 } 347 return 1; 348 } 349 350 /* Fixup msi node for ls1043a rev1.1*/ 351 352 static void fdt_fixup_msi(void *blob) 353 { 354 struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); 355 unsigned int rev; 356 357 rev = gur_in32(&gur->svr); 358 359 if (!IS_SVR_DEV(rev, SVR_DEV(SVR_LS1043A))) 360 return; 361 362 rev = SVR_REV(rev); 363 364 _fdt_fixup_msi_node(blob, "/soc/msi-controller1@1571000", 365 116, 111, rev); 366 _fdt_fixup_msi_node(blob, "/soc/msi-controller2@1572000", 367 126, 121, rev); 368 _fdt_fixup_msi_node(blob, "/soc/msi-controller3@1573000", 369 160, 155, rev); 370 371 _fdt_fixup_pci_msi(blob, "/soc/pcie@3400000", rev); 372 _fdt_fixup_pci_msi(blob, "/soc/pcie@3500000", rev); 373 _fdt_fixup_pci_msi(blob, "/soc/pcie@3600000", rev); 374 } 375 #endif 376 377 #ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT 378 /* Remove JR node used by SEC firmware */ 379 void fdt_fixup_remove_jr(void *blob) 380 { 381 int jr_node, addr_cells, len; 382 int crypto_node = fdt_path_offset(blob, "crypto"); 383 u64 jr_offset, used_jr; 384 fdt32_t *reg; 385 386 used_jr = sec_firmware_used_jobring_offset(); 387 fdt_support_default_count_cells(blob, crypto_node, &addr_cells, NULL); 388 389 jr_node = fdt_node_offset_by_compatible(blob, crypto_node, 390 "fsl,sec-v4.0-job-ring"); 391 392 while (jr_node != -FDT_ERR_NOTFOUND) { 393 reg = (fdt32_t *)fdt_getprop(blob, jr_node, "reg", &len); 394 jr_offset = fdt_read_number(reg, addr_cells); 395 if (jr_offset == used_jr) { 396 fdt_del_node(blob, jr_node); 397 break; 398 } 399 jr_node = fdt_node_offset_by_compatible(blob, jr_node, 400 "fsl,sec-v4.0-job-ring"); 401 } 402 } 403 #endif 404 405 void ft_cpu_setup(void *blob, bd_t *bd) 406 { 407 struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); 408 unsigned int svr = gur_in32(&gur->svr); 409 410 /* delete crypto node if not on an E-processor */ 411 if (!IS_E_PROCESSOR(svr)) 412 fdt_fixup_crypto_node(blob, 0); 413 #if CONFIG_SYS_FSL_SEC_COMPAT >= 4 414 else { 415 ccsr_sec_t __iomem *sec; 416 417 #ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT 418 if (fdt_fixup_kaslr(blob)) 419 fdt_fixup_remove_jr(blob); 420 #endif 421 422 sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR; 423 fdt_fixup_crypto_node(blob, sec_in32(&sec->secvid_ms)); 424 } 425 #endif 426 427 #ifdef CONFIG_MP 428 ft_fixup_cpu(blob); 429 #endif 430 431 #ifdef CONFIG_SYS_NS16550 432 do_fixup_by_compat_u32(blob, "fsl,ns16550", 433 "clock-frequency", CONFIG_SYS_NS16550_CLK, 1); 434 #endif 435 436 do_fixup_by_path_u32(blob, "/sysclk", "clock-frequency", 437 CONFIG_SYS_CLK_FREQ, 1); 438 439 #ifdef CONFIG_PCI 440 ft_pci_setup(blob, bd); 441 #endif 442 443 #ifdef CONFIG_FSL_ESDHC 444 fdt_fixup_esdhc(blob, bd); 445 #endif 446 447 #ifdef CONFIG_SYS_DPAA_QBMAN 448 fdt_fixup_bportals(blob); 449 fdt_fixup_qportals(blob); 450 do_fixup_by_compat_u32(blob, "fsl,qman", 451 "clock-frequency", get_qman_freq(), 1); 452 #endif 453 454 #ifdef CONFIG_SYS_DPAA_FMAN 455 fdt_fixup_fman_firmware(blob); 456 #endif 457 #ifndef CONFIG_ARCH_LS1012A 458 fsl_fdt_disable_usb(blob); 459 #endif 460 #ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN 461 fdt_fixup_gic(blob); 462 #endif 463 #ifdef CONFIG_HAS_FEATURE_ENHANCED_MSI 464 fdt_fixup_msi(blob); 465 #endif 466 } 467