fdt.c 13 KB

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