19f3183d2SMingkai Hu /* 29f3183d2SMingkai Hu * Copyright 2014-2015 Freescale Semiconductor, Inc. 39f3183d2SMingkai Hu * 49f3183d2SMingkai Hu * SPDX-License-Identifier: GPL-2.0+ 59f3183d2SMingkai Hu */ 69f3183d2SMingkai Hu 79f3183d2SMingkai Hu #include <common.h> 89f3183d2SMingkai Hu #include <libfdt.h> 99f3183d2SMingkai Hu #include <fdt_support.h> 109f3183d2SMingkai Hu #include <phy.h> 119f3183d2SMingkai Hu #ifdef CONFIG_FSL_LSCH3 129f3183d2SMingkai Hu #include <asm/arch/fdt.h> 139f3183d2SMingkai Hu #endif 149f3183d2SMingkai Hu #ifdef CONFIG_FSL_ESDHC 159f3183d2SMingkai Hu #include <fsl_esdhc.h> 169f3183d2SMingkai Hu #endif 17*0e52b6feSQianyu Gong #ifdef CONFIG_SYS_DPAA_FMAN 18*0e52b6feSQianyu Gong #include <fsl_fman.h> 19*0e52b6feSQianyu Gong #endif 209f3183d2SMingkai Hu #ifdef CONFIG_MP 219f3183d2SMingkai Hu #include <asm/arch/mp.h> 229f3183d2SMingkai Hu #endif 239f3183d2SMingkai Hu 24e8297341SShaohui Xie int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc) 25e8297341SShaohui Xie { 26e8297341SShaohui Xie return fdt_setprop_string(blob, offset, "phy-connection-type", 27e8297341SShaohui Xie phy_string_for_interface(phyc)); 28e8297341SShaohui Xie } 29e8297341SShaohui Xie 309f3183d2SMingkai Hu #ifdef CONFIG_MP 319f3183d2SMingkai Hu void ft_fixup_cpu(void *blob) 329f3183d2SMingkai Hu { 339f3183d2SMingkai Hu int off; 349f3183d2SMingkai Hu __maybe_unused u64 spin_tbl_addr = (u64)get_spin_tbl_addr(); 359f3183d2SMingkai Hu fdt32_t *reg; 369f3183d2SMingkai Hu int addr_cells; 379f3183d2SMingkai Hu u64 val, core_id; 389f3183d2SMingkai Hu size_t *boot_code_size = &(__secondary_boot_code_size); 399f3183d2SMingkai Hu 409f3183d2SMingkai Hu off = fdt_path_offset(blob, "/cpus"); 419f3183d2SMingkai Hu if (off < 0) { 429f3183d2SMingkai Hu puts("couldn't find /cpus node\n"); 439f3183d2SMingkai Hu return; 449f3183d2SMingkai Hu } 459f3183d2SMingkai Hu of_bus_default_count_cells(blob, off, &addr_cells, NULL); 469f3183d2SMingkai Hu 479f3183d2SMingkai Hu off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); 489f3183d2SMingkai Hu while (off != -FDT_ERR_NOTFOUND) { 499f3183d2SMingkai Hu reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0); 509f3183d2SMingkai Hu if (reg) { 519f3183d2SMingkai Hu core_id = of_read_number(reg, addr_cells); 529f3183d2SMingkai Hu if (core_id == 0 || (is_core_online(core_id))) { 539f3183d2SMingkai Hu val = spin_tbl_addr; 549f3183d2SMingkai Hu val += id_to_core(core_id) * 559f3183d2SMingkai Hu SPIN_TABLE_ELEM_SIZE; 569f3183d2SMingkai Hu val = cpu_to_fdt64(val); 579f3183d2SMingkai Hu fdt_setprop_string(blob, off, "enable-method", 589f3183d2SMingkai Hu "spin-table"); 599f3183d2SMingkai Hu fdt_setprop(blob, off, "cpu-release-addr", 609f3183d2SMingkai Hu &val, sizeof(val)); 619f3183d2SMingkai Hu } else { 629f3183d2SMingkai Hu debug("skipping offline core\n"); 639f3183d2SMingkai Hu } 649f3183d2SMingkai Hu } else { 659f3183d2SMingkai Hu puts("Warning: found cpu node without reg property\n"); 669f3183d2SMingkai Hu } 679f3183d2SMingkai Hu off = fdt_node_offset_by_prop_value(blob, off, "device_type", 689f3183d2SMingkai Hu "cpu", 4); 699f3183d2SMingkai Hu } 709f3183d2SMingkai Hu 719f3183d2SMingkai Hu fdt_add_mem_rsv(blob, (uintptr_t)&secondary_boot_code, 729f3183d2SMingkai Hu *boot_code_size); 739f3183d2SMingkai Hu } 749f3183d2SMingkai Hu #endif 759f3183d2SMingkai Hu 769f3183d2SMingkai Hu /* 779f3183d2SMingkai Hu * the burden is on the the caller to not request a count 789f3183d2SMingkai Hu * exceeding the bounds of the stream_ids[] array 799f3183d2SMingkai Hu */ 809f3183d2SMingkai Hu void alloc_stream_ids(int start_id, int count, u32 *stream_ids, int max_cnt) 819f3183d2SMingkai Hu { 829f3183d2SMingkai Hu int i; 839f3183d2SMingkai Hu 849f3183d2SMingkai Hu if (count > max_cnt) { 859f3183d2SMingkai Hu printf("\n%s: ERROR: max per-device stream ID count exceed\n", 869f3183d2SMingkai Hu __func__); 879f3183d2SMingkai Hu return; 889f3183d2SMingkai Hu } 899f3183d2SMingkai Hu 909f3183d2SMingkai Hu for (i = 0; i < count; i++) 919f3183d2SMingkai Hu stream_ids[i] = start_id++; 929f3183d2SMingkai Hu } 939f3183d2SMingkai Hu 949f3183d2SMingkai Hu /* 959f3183d2SMingkai Hu * This function updates the mmu-masters property on the SMMU 969f3183d2SMingkai Hu * node as per the SMMU binding-- phandle and list of stream IDs 979f3183d2SMingkai Hu * for each MMU master. 989f3183d2SMingkai Hu */ 999f3183d2SMingkai Hu void append_mmu_masters(void *blob, const char *smmu_path, 1009f3183d2SMingkai Hu const char *master_name, u32 *stream_ids, int count) 1019f3183d2SMingkai Hu { 1029f3183d2SMingkai Hu u32 phandle; 1039f3183d2SMingkai Hu int smmu_nodeoffset; 1049f3183d2SMingkai Hu int master_nodeoffset; 1059f3183d2SMingkai Hu int i; 1069f3183d2SMingkai Hu 1079f3183d2SMingkai Hu /* get phandle of mmu master device */ 1089f3183d2SMingkai Hu master_nodeoffset = fdt_path_offset(blob, master_name); 1099f3183d2SMingkai Hu if (master_nodeoffset < 0) { 1109f3183d2SMingkai Hu printf("\n%s: ERROR: master not found\n", __func__); 1119f3183d2SMingkai Hu return; 1129f3183d2SMingkai Hu } 1139f3183d2SMingkai Hu phandle = fdt_get_phandle(blob, master_nodeoffset); 1149f3183d2SMingkai Hu if (!phandle) { /* if master has no phandle, create one */ 1159f3183d2SMingkai Hu phandle = fdt_create_phandle(blob, master_nodeoffset); 1169f3183d2SMingkai Hu if (!phandle) { 1179f3183d2SMingkai Hu printf("\n%s: ERROR: unable to create phandle\n", 1189f3183d2SMingkai Hu __func__); 1199f3183d2SMingkai Hu return; 1209f3183d2SMingkai Hu } 1219f3183d2SMingkai Hu } 1229f3183d2SMingkai Hu 1239f3183d2SMingkai Hu /* append it to mmu-masters */ 1249f3183d2SMingkai Hu smmu_nodeoffset = fdt_path_offset(blob, smmu_path); 1259f3183d2SMingkai Hu if (fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters", 1269f3183d2SMingkai Hu phandle) < 0) { 1279f3183d2SMingkai Hu printf("\n%s: ERROR: unable to update SMMU node\n", __func__); 1289f3183d2SMingkai Hu return; 1299f3183d2SMingkai Hu } 1309f3183d2SMingkai Hu 1319f3183d2SMingkai Hu /* for each stream ID, append to mmu-masters */ 1329f3183d2SMingkai Hu for (i = 0; i < count; i++) { 1339f3183d2SMingkai Hu fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters", 1349f3183d2SMingkai Hu stream_ids[i]); 1359f3183d2SMingkai Hu } 1369f3183d2SMingkai Hu 1379f3183d2SMingkai Hu /* fix up #stream-id-cells with stream ID count */ 1389f3183d2SMingkai Hu if (fdt_setprop_u32(blob, master_nodeoffset, "#stream-id-cells", 1399f3183d2SMingkai Hu count) < 0) 1409f3183d2SMingkai Hu printf("\n%s: ERROR: unable to update #stream-id-cells\n", 1419f3183d2SMingkai Hu __func__); 1429f3183d2SMingkai Hu } 1439f3183d2SMingkai Hu 1449f3183d2SMingkai Hu 1459f3183d2SMingkai Hu /* 1469f3183d2SMingkai Hu * The info below summarizes how streamID partitioning works 14744937214SPrabhakar Kushwaha * for ls2080a and how it is conveyed to the OS via the device tree. 1489f3183d2SMingkai Hu * 1499f3183d2SMingkai Hu * -non-PCI legacy, platform devices (USB, SD/MMC, SATA, DMA) 1509f3183d2SMingkai Hu * -all legacy devices get a unique ICID assigned and programmed in 1519f3183d2SMingkai Hu * their AMQR registers by u-boot 1529f3183d2SMingkai Hu * -u-boot updates the hardware device tree with streamID properties 1539f3183d2SMingkai Hu * for each platform/legacy device (smmu-masters property) 1549f3183d2SMingkai Hu * 1559f3183d2SMingkai Hu * -PCIe 1569f3183d2SMingkai Hu * -for each PCI controller that is active (as per RCW settings), 1579f3183d2SMingkai Hu * u-boot will allocate a range of ICID and convey that to Linux via 1589f3183d2SMingkai Hu * the device tree (smmu-masters property) 1599f3183d2SMingkai Hu * 1609f3183d2SMingkai Hu * -DPAA2 1619f3183d2SMingkai Hu * -u-boot will allocate a range of ICIDs to be used by the Management 1629f3183d2SMingkai Hu * Complex for containers and will set these values in the MC DPC image. 1639f3183d2SMingkai Hu * -the MC is responsible for allocating and setting up ICIDs 1649f3183d2SMingkai Hu * for all DPAA2 devices. 1659f3183d2SMingkai Hu * 1669f3183d2SMingkai Hu */ 1679f3183d2SMingkai Hu #ifdef CONFIG_FSL_LSCH3 1689f3183d2SMingkai Hu static void fdt_fixup_smmu(void *blob) 1699f3183d2SMingkai Hu { 1709f3183d2SMingkai Hu int nodeoffset; 1719f3183d2SMingkai Hu 1729f3183d2SMingkai Hu nodeoffset = fdt_path_offset(blob, "/iommu@5000000"); 1739f3183d2SMingkai Hu if (nodeoffset < 0) { 1749f3183d2SMingkai Hu printf("\n%s: WARNING: no SMMU node found\n", __func__); 1759f3183d2SMingkai Hu return; 1769f3183d2SMingkai Hu } 1779f3183d2SMingkai Hu 1789f3183d2SMingkai Hu /* fixup for all PCI controllers */ 1799f3183d2SMingkai Hu #ifdef CONFIG_PCI 1809f3183d2SMingkai Hu fdt_fixup_smmu_pcie(blob); 1819f3183d2SMingkai Hu #endif 1829f3183d2SMingkai Hu } 1839f3183d2SMingkai Hu #endif 1849f3183d2SMingkai Hu 1859f3183d2SMingkai Hu void ft_cpu_setup(void *blob, bd_t *bd) 1869f3183d2SMingkai Hu { 1879f3183d2SMingkai Hu #ifdef CONFIG_MP 1889f3183d2SMingkai Hu ft_fixup_cpu(blob); 1899f3183d2SMingkai Hu #endif 1909f3183d2SMingkai Hu 1919f3183d2SMingkai Hu #ifdef CONFIG_SYS_NS16550 1929f3183d2SMingkai Hu do_fixup_by_compat_u32(blob, "fsl,ns16550", 1939f3183d2SMingkai Hu "clock-frequency", CONFIG_SYS_NS16550_CLK, 1); 1949f3183d2SMingkai Hu #endif 1959f3183d2SMingkai Hu 1966f14e257SPrabhakar Kushwaha do_fixup_by_compat_u32(blob, "fixed-clock", 1976f14e257SPrabhakar Kushwaha "clock-frequency", CONFIG_SYS_CLK_FREQ, 1); 1986f14e257SPrabhakar Kushwaha 1999f3183d2SMingkai Hu #ifdef CONFIG_PCI 2009f3183d2SMingkai Hu ft_pci_setup(blob, bd); 2019f3183d2SMingkai Hu #endif 2029f3183d2SMingkai Hu 2039f3183d2SMingkai Hu #ifdef CONFIG_FSL_ESDHC 2049f3183d2SMingkai Hu fdt_fixup_esdhc(blob, bd); 2059f3183d2SMingkai Hu #endif 2069f3183d2SMingkai Hu 2079f3183d2SMingkai Hu #ifdef CONFIG_FSL_LSCH3 2089f3183d2SMingkai Hu fdt_fixup_smmu(blob); 2099f3183d2SMingkai Hu #endif 210*0e52b6feSQianyu Gong 211*0e52b6feSQianyu Gong #ifdef CONFIG_SYS_DPAA_FMAN 212*0e52b6feSQianyu Gong fdt_fixup_fman_firmware(blob); 213*0e52b6feSQianyu Gong #endif 2149f3183d2SMingkai Hu } 215