]>
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> | |
5a37a2f0 | 8 | #include <efi_loader.h> |
40f8dec5 YS |
9 | #include <libfdt.h> |
10 | #include <fdt_support.h> | |
9f3183d2 MH |
11 | #include <phy.h> |
12 | #ifdef CONFIG_FSL_LSCH3 | |
13 | #include <asm/arch/fdt.h> | |
14 | #endif | |
8b06460e YL |
15 | #ifdef CONFIG_FSL_ESDHC |
16 | #include <fsl_esdhc.h> | |
17 | #endif | |
0e52b6fe QG |
18 | #ifdef CONFIG_SYS_DPAA_FMAN |
19 | #include <fsl_fman.h> | |
20 | #endif | |
9f3183d2 MH |
21 | #ifdef CONFIG_MP |
22 | #include <asm/arch/mp.h> | |
23 | #endif | |
f13c99c2 AP |
24 | #include <fsl_sec.h> |
25 | #include <asm/arch-fsl-layerscape/soc.h> | |
032d5bb4 HZ |
26 | #ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT |
27 | #include <asm/armv8/sec_firmware.h> | |
28 | #endif | |
40f8dec5 | 29 | |
e8297341 SX |
30 | int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc) |
31 | { | |
32 | return fdt_setprop_string(blob, offset, "phy-connection-type", | |
33 | phy_string_for_interface(phyc)); | |
34 | } | |
35 | ||
40f8dec5 YS |
36 | #ifdef CONFIG_MP |
37 | void ft_fixup_cpu(void *blob) | |
38 | { | |
39 | int off; | |
40 | __maybe_unused u64 spin_tbl_addr = (u64)get_spin_tbl_addr(); | |
41 | fdt32_t *reg; | |
42 | int addr_cells; | |
60385d94 | 43 | u64 val, core_id; |
40f8dec5 | 44 | size_t *boot_code_size = &(__secondary_boot_code_size); |
2d16a1a6 | 45 | #if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) && \ |
46 | defined(CONFIG_FSL_PPA_ARMV8_PSCI) | |
032d5bb4 HZ |
47 | int node; |
48 | u32 psci_ver; | |
49 | ||
50 | /* Check the psci version to determine if the psci is supported */ | |
51 | psci_ver = sec_firmware_support_psci_version(); | |
52 | if (psci_ver == 0xffffffff) { | |
53 | /* remove psci DT node */ | |
54 | node = fdt_path_offset(blob, "/psci"); | |
55 | if (node >= 0) | |
56 | goto remove_psci_node; | |
57 | ||
58 | node = fdt_node_offset_by_compatible(blob, -1, "arm,psci"); | |
59 | if (node >= 0) | |
60 | goto remove_psci_node; | |
61 | ||
62 | node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-0.2"); | |
63 | if (node >= 0) | |
64 | goto remove_psci_node; | |
40f8dec5 | 65 | |
032d5bb4 HZ |
66 | node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-1.0"); |
67 | if (node >= 0) | |
68 | goto remove_psci_node; | |
69 | ||
70 | remove_psci_node: | |
71 | if (node >= 0) | |
72 | fdt_del_node(blob, node); | |
73 | } else { | |
74 | return; | |
75 | } | |
76 | #endif | |
40f8dec5 YS |
77 | off = fdt_path_offset(blob, "/cpus"); |
78 | if (off < 0) { | |
79 | puts("couldn't find /cpus node\n"); | |
80 | return; | |
81 | } | |
82 | of_bus_default_count_cells(blob, off, &addr_cells, NULL); | |
83 | ||
84 | off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); | |
85 | while (off != -FDT_ERR_NOTFOUND) { | |
86 | reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0); | |
87 | if (reg) { | |
6a00a9cb | 88 | core_id = of_read_number(reg, addr_cells); |
60385d94 AB |
89 | if (core_id == 0 || (is_core_online(core_id))) { |
90 | val = spin_tbl_addr; | |
91 | val += id_to_core(core_id) * | |
92 | SPIN_TABLE_ELEM_SIZE; | |
93 | val = cpu_to_fdt64(val); | |
94 | fdt_setprop_string(blob, off, "enable-method", | |
95 | "spin-table"); | |
96 | fdt_setprop(blob, off, "cpu-release-addr", | |
97 | &val, sizeof(val)); | |
98 | } else { | |
99 | debug("skipping offline core\n"); | |
100 | } | |
40f8dec5 YS |
101 | } else { |
102 | puts("Warning: found cpu node without reg property\n"); | |
103 | } | |
104 | off = fdt_node_offset_by_prop_value(blob, off, "device_type", | |
105 | "cpu", 4); | |
106 | } | |
107 | ||
108 | fdt_add_mem_rsv(blob, (uintptr_t)&secondary_boot_code, | |
109 | *boot_code_size); | |
5a37a2f0 AG |
110 | #if defined(CONFIG_EFI_LOADER) && !defined(CONFIG_SPL_BUILD) |
111 | efi_add_memory_map((uintptr_t)&secondary_boot_code, | |
112 | ALIGN(*boot_code_size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT, | |
113 | EFI_RESERVED_MEMORY_TYPE, false); | |
114 | #endif | |
40f8dec5 YS |
115 | } |
116 | #endif | |
117 | ||
c93db4f7 SD |
118 | void fsl_fdt_disable_usb(void *blob) |
119 | { | |
120 | int off; | |
121 | /* | |
122 | * SYSCLK is used as a reference clock for USB. When the USB | |
123 | * controller is used, SYSCLK must meet the additional requirement | |
124 | * of 100 MHz. | |
125 | */ | |
126 | if (CONFIG_SYS_CLK_FREQ != 100000000) { | |
127 | off = fdt_node_offset_by_compatible(blob, -1, "snps,dwc3"); | |
128 | while (off != -FDT_ERR_NOTFOUND) { | |
129 | fdt_status_disabled(blob, off); | |
130 | off = fdt_node_offset_by_compatible(blob, off, | |
131 | "snps,dwc3"); | |
132 | } | |
133 | } | |
134 | } | |
135 | ||
fa18ed76 WS |
136 | #ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN |
137 | static void fdt_fixup_gic(void *blob) | |
138 | { | |
139 | int offset, err; | |
140 | u64 reg[8]; | |
141 | struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); | |
142 | unsigned int val; | |
143 | struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR; | |
144 | int align_64k = 0; | |
145 | ||
146 | val = gur_in32(&gur->svr); | |
147 | ||
148 | if (SVR_SOC_VER(val) != SVR_LS1043A) { | |
149 | align_64k = 1; | |
150 | } else if (SVR_REV(val) != REV1_0) { | |
151 | val = scfg_in32(&scfg->gic_align) & (0x01 << GIC_ADDR_BIT); | |
152 | if (!val) | |
153 | align_64k = 1; | |
154 | } | |
155 | ||
156 | offset = fdt_subnode_offset(blob, 0, "interrupt-controller@1400000"); | |
157 | if (offset < 0) { | |
158 | printf("WARNING: fdt_subnode_offset can't find node %s: %s\n", | |
159 | "interrupt-controller@1400000", fdt_strerror(offset)); | |
160 | return; | |
161 | } | |
162 | ||
163 | /* Fixup gic node align with 64K */ | |
164 | if (align_64k) { | |
165 | reg[0] = cpu_to_fdt64(GICD_BASE_64K); | |
166 | reg[1] = cpu_to_fdt64(GICD_SIZE_64K); | |
167 | reg[2] = cpu_to_fdt64(GICC_BASE_64K); | |
168 | reg[3] = cpu_to_fdt64(GICC_SIZE_64K); | |
169 | reg[4] = cpu_to_fdt64(GICH_BASE_64K); | |
170 | reg[5] = cpu_to_fdt64(GICH_SIZE_64K); | |
171 | reg[6] = cpu_to_fdt64(GICV_BASE_64K); | |
172 | reg[7] = cpu_to_fdt64(GICV_SIZE_64K); | |
173 | } else { | |
174 | /* Fixup gic node align with default */ | |
175 | reg[0] = cpu_to_fdt64(GICD_BASE); | |
176 | reg[1] = cpu_to_fdt64(GICD_SIZE); | |
177 | reg[2] = cpu_to_fdt64(GICC_BASE); | |
178 | reg[3] = cpu_to_fdt64(GICC_SIZE); | |
179 | reg[4] = cpu_to_fdt64(GICH_BASE); | |
180 | reg[5] = cpu_to_fdt64(GICH_SIZE); | |
181 | reg[6] = cpu_to_fdt64(GICV_BASE); | |
182 | reg[7] = cpu_to_fdt64(GICV_SIZE); | |
183 | } | |
184 | ||
185 | err = fdt_setprop(blob, offset, "reg", reg, sizeof(reg)); | |
186 | if (err < 0) { | |
187 | printf("WARNING: fdt_setprop can't set %s from node %s: %s\n", | |
188 | "reg", "interrupt-controller@1400000", | |
189 | fdt_strerror(err)); | |
190 | return; | |
191 | } | |
192 | ||
193 | return; | |
194 | } | |
195 | #endif | |
196 | ||
2ca84bf7 WS |
197 | #ifdef CONFIG_HAS_FEATURE_ENHANCED_MSI |
198 | static int _fdt_fixup_msi_node(void *blob, const char *name, | |
199 | int irq_0, int irq_1, int rev) | |
200 | { | |
201 | int err, offset, len; | |
202 | u32 tmp[4][3]; | |
203 | void *p; | |
204 | ||
205 | offset = fdt_path_offset(blob, name); | |
206 | if (offset < 0) { | |
207 | printf("WARNING: fdt_path_offset can't find path %s: %s\n", | |
208 | name, fdt_strerror(offset)); | |
209 | return 0; | |
210 | } | |
211 | ||
212 | /*fixup the property of interrupts*/ | |
213 | ||
214 | tmp[0][0] = cpu_to_fdt32(0x0); | |
215 | tmp[0][1] = cpu_to_fdt32(irq_0); | |
216 | tmp[0][2] = cpu_to_fdt32(0x4); | |
217 | ||
218 | if (rev > REV1_0) { | |
219 | tmp[1][0] = cpu_to_fdt32(0x0); | |
220 | tmp[1][1] = cpu_to_fdt32(irq_1); | |
221 | tmp[1][2] = cpu_to_fdt32(0x4); | |
222 | tmp[2][0] = cpu_to_fdt32(0x0); | |
223 | tmp[2][1] = cpu_to_fdt32(irq_1 + 1); | |
224 | tmp[2][2] = cpu_to_fdt32(0x4); | |
225 | tmp[3][0] = cpu_to_fdt32(0x0); | |
226 | tmp[3][1] = cpu_to_fdt32(irq_1 + 2); | |
227 | tmp[3][2] = cpu_to_fdt32(0x4); | |
228 | len = sizeof(tmp); | |
229 | } else { | |
230 | len = sizeof(tmp[0]); | |
231 | } | |
232 | ||
233 | err = fdt_setprop(blob, offset, "interrupts", tmp, len); | |
234 | if (err < 0) { | |
235 | printf("WARNING: fdt_setprop can't set %s from node %s: %s\n", | |
236 | "interrupts", name, fdt_strerror(err)); | |
237 | return 0; | |
238 | } | |
239 | ||
240 | /*fixup the property of reg*/ | |
241 | p = (char *)fdt_getprop(blob, offset, "reg", &len); | |
242 | if (!p) { | |
243 | printf("WARNING: fdt_getprop can't get %s from node %s\n", | |
244 | "reg", name); | |
245 | return 0; | |
246 | } | |
247 | ||
248 | memcpy((char *)tmp, p, len); | |
249 | ||
250 | if (rev > REV1_0) | |
251 | *((u32 *)tmp + 3) = cpu_to_fdt32(0x1000); | |
252 | else | |
253 | *((u32 *)tmp + 3) = cpu_to_fdt32(0x8); | |
254 | ||
255 | err = fdt_setprop(blob, offset, "reg", tmp, len); | |
256 | if (err < 0) { | |
257 | printf("WARNING: fdt_setprop can't set %s from node %s: %s\n", | |
258 | "reg", name, fdt_strerror(err)); | |
259 | return 0; | |
260 | } | |
261 | ||
262 | /*fixup the property of compatible*/ | |
263 | if (rev > REV1_0) | |
264 | err = fdt_setprop_string(blob, offset, "compatible", | |
265 | "fsl,ls1043a-v1.1-msi"); | |
266 | else | |
267 | err = fdt_setprop_string(blob, offset, "compatible", | |
268 | "fsl,ls1043a-msi"); | |
269 | if (err < 0) { | |
270 | printf("WARNING: fdt_setprop can't set %s from node %s: %s\n", | |
271 | "compatible", name, fdt_strerror(err)); | |
272 | return 0; | |
273 | } | |
274 | ||
275 | return 1; | |
276 | } | |
277 | ||
278 | static int _fdt_fixup_pci_msi(void *blob, const char *name, int rev) | |
279 | { | |
280 | int offset, len, err; | |
281 | void *p; | |
282 | int val; | |
283 | u32 tmp[4][8]; | |
284 | ||
285 | offset = fdt_path_offset(blob, name); | |
286 | if (offset < 0) { | |
287 | printf("WARNING: fdt_path_offset can't find path %s: %s\n", | |
288 | name, fdt_strerror(offset)); | |
289 | return 0; | |
290 | } | |
291 | ||
292 | p = (char *)fdt_getprop(blob, offset, "interrupt-map", &len); | |
293 | if (!p || len != sizeof(tmp)) { | |
294 | printf("WARNING: fdt_getprop can't get %s from node %s\n", | |
295 | "interrupt-map", name); | |
296 | return 0; | |
297 | } | |
298 | ||
299 | memcpy((char *)tmp, p, len); | |
300 | ||
301 | val = fdt32_to_cpu(tmp[0][6]); | |
302 | if (rev > REV1_0) { | |
303 | tmp[1][6] = cpu_to_fdt32(val + 1); | |
304 | tmp[2][6] = cpu_to_fdt32(val + 2); | |
305 | tmp[3][6] = cpu_to_fdt32(val + 3); | |
306 | } else { | |
307 | tmp[1][6] = cpu_to_fdt32(val); | |
308 | tmp[2][6] = cpu_to_fdt32(val); | |
309 | tmp[3][6] = cpu_to_fdt32(val); | |
310 | } | |
311 | ||
312 | err = fdt_setprop(blob, offset, "interrupt-map", tmp, sizeof(tmp)); | |
313 | if (err < 0) { | |
314 | printf("WARNING: fdt_setprop can't set %s from node %s: %s.\n", | |
315 | "interrupt-map", name, fdt_strerror(err)); | |
316 | return 0; | |
317 | } | |
318 | return 1; | |
319 | } | |
320 | ||
321 | /* Fixup msi node for ls1043a rev1.1*/ | |
322 | ||
323 | static void fdt_fixup_msi(void *blob) | |
324 | { | |
325 | struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); | |
326 | unsigned int rev; | |
327 | ||
328 | rev = gur_in32(&gur->svr); | |
329 | ||
330 | if (SVR_SOC_VER(rev) != SVR_LS1043A) | |
331 | return; | |
332 | ||
333 | rev = SVR_REV(rev); | |
334 | ||
335 | _fdt_fixup_msi_node(blob, "/soc/msi-controller1@1571000", | |
336 | 116, 111, rev); | |
337 | _fdt_fixup_msi_node(blob, "/soc/msi-controller2@1572000", | |
338 | 126, 121, rev); | |
339 | _fdt_fixup_msi_node(blob, "/soc/msi-controller3@1573000", | |
340 | 160, 155, rev); | |
341 | ||
342 | _fdt_fixup_pci_msi(blob, "/soc/pcie@3400000", rev); | |
343 | _fdt_fixup_pci_msi(blob, "/soc/pcie@3500000", rev); | |
344 | _fdt_fixup_pci_msi(blob, "/soc/pcie@3600000", rev); | |
345 | } | |
346 | #endif | |
347 | ||
40f8dec5 YS |
348 | void ft_cpu_setup(void *blob, bd_t *bd) |
349 | { | |
f13c99c2 AP |
350 | #ifdef CONFIG_FSL_LSCH2 |
351 | struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); | |
352 | unsigned int svr = in_be32(&gur->svr); | |
353 | ||
354 | /* delete crypto node if not on an E-processor */ | |
355 | if (!IS_E_PROCESSOR(svr)) | |
356 | fdt_fixup_crypto_node(blob, 0); | |
357 | #if CONFIG_SYS_FSL_SEC_COMPAT >= 4 | |
358 | else { | |
359 | ccsr_sec_t __iomem *sec; | |
360 | ||
361 | sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR; | |
362 | fdt_fixup_crypto_node(blob, sec_in32(&sec->secvid_ms)); | |
363 | } | |
364 | #endif | |
365 | #endif | |
366 | ||
40f8dec5 YS |
367 | #ifdef CONFIG_MP |
368 | ft_fixup_cpu(blob); | |
369 | #endif | |
912cc40f BS |
370 | |
371 | #ifdef CONFIG_SYS_NS16550 | |
1e52835a | 372 | do_fixup_by_compat_u32(blob, "fsl,ns16550", |
912cc40f BS |
373 | "clock-frequency", CONFIG_SYS_NS16550_CLK, 1); |
374 | #endif | |
8b06460e | 375 | |
6f14e257 PK |
376 | do_fixup_by_compat_u32(blob, "fixed-clock", |
377 | "clock-frequency", CONFIG_SYS_CLK_FREQ, 1); | |
378 | ||
5be3b44c PK |
379 | #ifdef CONFIG_PCI |
380 | ft_pci_setup(blob, bd); | |
381 | #endif | |
382 | ||
9f3183d2 | 383 | #ifdef CONFIG_FSL_ESDHC |
8b06460e YL |
384 | fdt_fixup_esdhc(blob, bd); |
385 | #endif | |
70e52d21 | 386 | |
0e52b6fe QG |
387 | #ifdef CONFIG_SYS_DPAA_FMAN |
388 | fdt_fixup_fman_firmware(blob); | |
389 | #endif | |
c93db4f7 SD |
390 | fsl_fdt_disable_usb(blob); |
391 | ||
fa18ed76 WS |
392 | #ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN |
393 | fdt_fixup_gic(blob); | |
394 | #endif | |
2ca84bf7 WS |
395 | #ifdef CONFIG_HAS_FEATURE_ENHANCED_MSI |
396 | fdt_fixup_msi(blob); | |
397 | #endif | |
40f8dec5 | 398 | } |