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