]>
Commit | Line | Data |
---|---|---|
40f8dec5 | 1 | /* |
9f3183d2 | 2 | * Copyright 2014-2015 Freescale Semiconductor, Inc. |
40f8dec5 YS |
3 | * |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
8 | #include <libfdt.h> | |
9 | #include <fdt_support.h> | |
9f3183d2 MH |
10 | #include <phy.h> |
11 | #ifdef CONFIG_FSL_LSCH3 | |
12 | #include <asm/arch/fdt.h> | |
13 | #endif | |
8b06460e YL |
14 | #ifdef CONFIG_FSL_ESDHC |
15 | #include <fsl_esdhc.h> | |
16 | #endif | |
9f3183d2 MH |
17 | #ifdef CONFIG_MP |
18 | #include <asm/arch/mp.h> | |
19 | #endif | |
40f8dec5 | 20 | |
e8297341 SX |
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 | ||
40f8dec5 YS |
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; | |
60385d94 | 34 | u64 val, core_id; |
40f8dec5 YS |
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) { | |
6a00a9cb | 48 | core_id = of_read_number(reg, addr_cells); |
60385d94 AB |
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 | } | |
40f8dec5 YS |
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 | ||
70e52d21 SY |
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 | |
44937214 | 144 | * for ls2080a and how it is conveyed to the OS via the device tree. |
70e52d21 SY |
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 | */ | |
9f3183d2 | 164 | #ifdef CONFIG_FSL_LSCH3 |
70e52d21 SY |
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 | } | |
9f3183d2 | 180 | #endif |
70e52d21 | 181 | |
40f8dec5 YS |
182 | void ft_cpu_setup(void *blob, bd_t *bd) |
183 | { | |
184 | #ifdef CONFIG_MP | |
185 | ft_fixup_cpu(blob); | |
186 | #endif | |
912cc40f BS |
187 | |
188 | #ifdef CONFIG_SYS_NS16550 | |
1e52835a | 189 | do_fixup_by_compat_u32(blob, "fsl,ns16550", |
912cc40f BS |
190 | "clock-frequency", CONFIG_SYS_NS16550_CLK, 1); |
191 | #endif | |
8b06460e | 192 | |
5be3b44c PK |
193 | #ifdef CONFIG_PCI |
194 | ft_pci_setup(blob, bd); | |
195 | #endif | |
196 | ||
9f3183d2 | 197 | #ifdef CONFIG_FSL_ESDHC |
8b06460e YL |
198 | fdt_fixup_esdhc(blob, bd); |
199 | #endif | |
70e52d21 | 200 | |
9f3183d2 | 201 | #ifdef CONFIG_FSL_LSCH3 |
70e52d21 | 202 | fdt_fixup_smmu(blob); |
9f3183d2 | 203 | #endif |
40f8dec5 | 204 | } |