York Sun | 56cc3db | 2014-09-08 12:20:00 -0700 | [diff] [blame] | 1 | /* |
Mingkai Hu | 0e58b51 | 2015-10-26 19:47:50 +0800 | [diff] [blame] | 2 | * Copyright 2014-2015 Freescale Semiconductor, Inc. |
York Sun | 56cc3db | 2014-09-08 12:20:00 -0700 | [diff] [blame] | 3 | * |
| 4 | * SPDX-License-Identifier: GPL-2.0+ |
| 5 | */ |
| 6 | |
| 7 | #include <common.h> |
| 8 | #include <libfdt.h> |
| 9 | #include <fdt_support.h> |
Mingkai Hu | 0e58b51 | 2015-10-26 19:47:50 +0800 | [diff] [blame] | 10 | #include <phy.h> |
| 11 | #ifdef CONFIG_FSL_LSCH3 |
| 12 | #include <asm/arch/fdt.h> |
| 13 | #endif |
Yangbo Lu | d0e295d | 2015-03-20 19:28:31 -0700 | [diff] [blame] | 14 | #ifdef CONFIG_FSL_ESDHC |
| 15 | #include <fsl_esdhc.h> |
| 16 | #endif |
Mingkai Hu | 0e58b51 | 2015-10-26 19:47:50 +0800 | [diff] [blame] | 17 | #ifdef CONFIG_MP |
| 18 | #include <asm/arch/mp.h> |
| 19 | #endif |
York Sun | 56cc3db | 2014-09-08 12:20:00 -0700 | [diff] [blame] | 20 | |
Shaohui Xie | 0464326 | 2015-10-26 19:47:54 +0800 | [diff] [blame] | 21 | int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc) |
| 22 | { |
| 23 | return fdt_setprop_string(blob, offset, "phy-connection-type", |
| 24 | phy_string_for_interface(phyc)); |
| 25 | } |
| 26 | |
York Sun | 56cc3db | 2014-09-08 12:20:00 -0700 | [diff] [blame] | 27 | #ifdef CONFIG_MP |
| 28 | void ft_fixup_cpu(void *blob) |
| 29 | { |
| 30 | int off; |
| 31 | __maybe_unused u64 spin_tbl_addr = (u64)get_spin_tbl_addr(); |
| 32 | fdt32_t *reg; |
| 33 | int addr_cells; |
Arnab Basu | 0cb1942 | 2015-01-06 13:18:41 -0800 | [diff] [blame] | 34 | u64 val, core_id; |
York Sun | 56cc3db | 2014-09-08 12:20:00 -0700 | [diff] [blame] | 35 | size_t *boot_code_size = &(__secondary_boot_code_size); |
| 36 | |
| 37 | off = fdt_path_offset(blob, "/cpus"); |
| 38 | if (off < 0) { |
| 39 | puts("couldn't find /cpus node\n"); |
| 40 | return; |
| 41 | } |
| 42 | of_bus_default_count_cells(blob, off, &addr_cells, NULL); |
| 43 | |
| 44 | off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); |
| 45 | while (off != -FDT_ERR_NOTFOUND) { |
| 46 | reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0); |
| 47 | if (reg) { |
Alison Wang | a978fc1 | 2015-09-01 10:47:27 +0800 | [diff] [blame] | 48 | core_id = of_read_number(reg, addr_cells); |
Arnab Basu | 0cb1942 | 2015-01-06 13:18:41 -0800 | [diff] [blame] | 49 | if (core_id == 0 || (is_core_online(core_id))) { |
| 50 | val = spin_tbl_addr; |
| 51 | val += id_to_core(core_id) * |
| 52 | SPIN_TABLE_ELEM_SIZE; |
| 53 | val = cpu_to_fdt64(val); |
| 54 | fdt_setprop_string(blob, off, "enable-method", |
| 55 | "spin-table"); |
| 56 | fdt_setprop(blob, off, "cpu-release-addr", |
| 57 | &val, sizeof(val)); |
| 58 | } else { |
| 59 | debug("skipping offline core\n"); |
| 60 | } |
York Sun | 56cc3db | 2014-09-08 12:20:00 -0700 | [diff] [blame] | 61 | } else { |
| 62 | puts("Warning: found cpu node without reg property\n"); |
| 63 | } |
| 64 | off = fdt_node_offset_by_prop_value(blob, off, "device_type", |
| 65 | "cpu", 4); |
| 66 | } |
| 67 | |
| 68 | fdt_add_mem_rsv(blob, (uintptr_t)&secondary_boot_code, |
| 69 | *boot_code_size); |
| 70 | } |
| 71 | #endif |
| 72 | |
Stuart Yoder | eaea504 | 2015-07-02 11:29:04 +0530 | [diff] [blame] | 73 | /* |
| 74 | * the burden is on the the caller to not request a count |
| 75 | * exceeding the bounds of the stream_ids[] array |
| 76 | */ |
| 77 | void alloc_stream_ids(int start_id, int count, u32 *stream_ids, int max_cnt) |
| 78 | { |
| 79 | int i; |
| 80 | |
| 81 | if (count > max_cnt) { |
| 82 | printf("\n%s: ERROR: max per-device stream ID count exceed\n", |
| 83 | __func__); |
| 84 | return; |
| 85 | } |
| 86 | |
| 87 | for (i = 0; i < count; i++) |
| 88 | stream_ids[i] = start_id++; |
| 89 | } |
| 90 | |
| 91 | /* |
| 92 | * This function updates the mmu-masters property on the SMMU |
| 93 | * node as per the SMMU binding-- phandle and list of stream IDs |
| 94 | * for each MMU master. |
| 95 | */ |
| 96 | void append_mmu_masters(void *blob, const char *smmu_path, |
| 97 | const char *master_name, u32 *stream_ids, int count) |
| 98 | { |
| 99 | u32 phandle; |
| 100 | int smmu_nodeoffset; |
| 101 | int master_nodeoffset; |
| 102 | int i; |
| 103 | |
| 104 | /* get phandle of mmu master device */ |
| 105 | master_nodeoffset = fdt_path_offset(blob, master_name); |
| 106 | if (master_nodeoffset < 0) { |
| 107 | printf("\n%s: ERROR: master not found\n", __func__); |
| 108 | return; |
| 109 | } |
| 110 | phandle = fdt_get_phandle(blob, master_nodeoffset); |
| 111 | if (!phandle) { /* if master has no phandle, create one */ |
| 112 | phandle = fdt_create_phandle(blob, master_nodeoffset); |
| 113 | if (!phandle) { |
| 114 | printf("\n%s: ERROR: unable to create phandle\n", |
| 115 | __func__); |
| 116 | return; |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | /* append it to mmu-masters */ |
| 121 | smmu_nodeoffset = fdt_path_offset(blob, smmu_path); |
| 122 | if (fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters", |
| 123 | phandle) < 0) { |
| 124 | printf("\n%s: ERROR: unable to update SMMU node\n", __func__); |
| 125 | return; |
| 126 | } |
| 127 | |
| 128 | /* for each stream ID, append to mmu-masters */ |
| 129 | for (i = 0; i < count; i++) { |
| 130 | fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters", |
| 131 | stream_ids[i]); |
| 132 | } |
| 133 | |
| 134 | /* fix up #stream-id-cells with stream ID count */ |
| 135 | if (fdt_setprop_u32(blob, master_nodeoffset, "#stream-id-cells", |
| 136 | count) < 0) |
| 137 | printf("\n%s: ERROR: unable to update #stream-id-cells\n", |
| 138 | __func__); |
| 139 | } |
| 140 | |
| 141 | |
| 142 | /* |
| 143 | * The info below summarizes how streamID partitioning works |
| 144 | * for ls2085a and how it is conveyed to the OS via the device tree. |
| 145 | * |
| 146 | * -non-PCI legacy, platform devices (USB, SD/MMC, SATA, DMA) |
| 147 | * -all legacy devices get a unique ICID assigned and programmed in |
| 148 | * their AMQR registers by u-boot |
| 149 | * -u-boot updates the hardware device tree with streamID properties |
| 150 | * for each platform/legacy device (smmu-masters property) |
| 151 | * |
| 152 | * -PCIe |
| 153 | * -for each PCI controller that is active (as per RCW settings), |
| 154 | * u-boot will allocate a range of ICID and convey that to Linux via |
| 155 | * the device tree (smmu-masters property) |
| 156 | * |
| 157 | * -DPAA2 |
| 158 | * -u-boot will allocate a range of ICIDs to be used by the Management |
| 159 | * Complex for containers and will set these values in the MC DPC image. |
| 160 | * -the MC is responsible for allocating and setting up ICIDs |
| 161 | * for all DPAA2 devices. |
| 162 | * |
| 163 | */ |
Mingkai Hu | 0e58b51 | 2015-10-26 19:47:50 +0800 | [diff] [blame] | 164 | #ifdef CONFIG_FSL_LSCH3 |
Stuart Yoder | eaea504 | 2015-07-02 11:29:04 +0530 | [diff] [blame] | 165 | static void fdt_fixup_smmu(void *blob) |
| 166 | { |
| 167 | int nodeoffset; |
| 168 | |
| 169 | nodeoffset = fdt_path_offset(blob, "/iommu@5000000"); |
| 170 | if (nodeoffset < 0) { |
| 171 | printf("\n%s: WARNING: no SMMU node found\n", __func__); |
| 172 | return; |
| 173 | } |
| 174 | |
| 175 | /* fixup for all PCI controllers */ |
| 176 | #ifdef CONFIG_PCI |
| 177 | fdt_fixup_smmu_pcie(blob); |
| 178 | #endif |
| 179 | } |
Mingkai Hu | 0e58b51 | 2015-10-26 19:47:50 +0800 | [diff] [blame] | 180 | #endif |
Stuart Yoder | eaea504 | 2015-07-02 11:29:04 +0530 | [diff] [blame] | 181 | |
York Sun | 56cc3db | 2014-09-08 12:20:00 -0700 | [diff] [blame] | 182 | void ft_cpu_setup(void *blob, bd_t *bd) |
| 183 | { |
| 184 | #ifdef CONFIG_MP |
| 185 | ft_fixup_cpu(blob); |
| 186 | #endif |
Bhupesh Sharma | c771040 | 2015-01-06 13:18:44 -0800 | [diff] [blame] | 187 | |
| 188 | #ifdef CONFIG_SYS_NS16550 |
Scott Wood | 3e7fd6f | 2015-03-20 19:28:14 -0700 | [diff] [blame] | 189 | do_fixup_by_compat_u32(blob, "fsl,ns16550", |
Bhupesh Sharma | c771040 | 2015-01-06 13:18:44 -0800 | [diff] [blame] | 190 | "clock-frequency", CONFIG_SYS_NS16550_CLK, 1); |
| 191 | #endif |
Yangbo Lu | d0e295d | 2015-03-20 19:28:31 -0700 | [diff] [blame] | 192 | |
Prabhakar Kushwaha | 940a316 | 2015-05-28 14:53:59 +0530 | [diff] [blame] | 193 | #ifdef CONFIG_PCI |
| 194 | ft_pci_setup(blob, bd); |
| 195 | #endif |
| 196 | |
Mingkai Hu | 0e58b51 | 2015-10-26 19:47:50 +0800 | [diff] [blame] | 197 | #ifdef CONFIG_FSL_ESDHC |
Yangbo Lu | d0e295d | 2015-03-20 19:28:31 -0700 | [diff] [blame] | 198 | fdt_fixup_esdhc(blob, bd); |
| 199 | #endif |
Stuart Yoder | eaea504 | 2015-07-02 11:29:04 +0530 | [diff] [blame] | 200 | |
Mingkai Hu | 0e58b51 | 2015-10-26 19:47:50 +0800 | [diff] [blame] | 201 | #ifdef CONFIG_FSL_LSCH3 |
Stuart Yoder | eaea504 | 2015-07-02 11:29:04 +0530 | [diff] [blame] | 202 | fdt_fixup_smmu(blob); |
Mingkai Hu | 0e58b51 | 2015-10-26 19:47:50 +0800 | [diff] [blame] | 203 | #endif |
York Sun | 56cc3db | 2014-09-08 12:20:00 -0700 | [diff] [blame] | 204 | } |