]>
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 YS |
20 | |
21 | #ifdef CONFIG_MP | |
22 | void ft_fixup_cpu(void *blob) | |
23 | { | |
24 | int off; | |
25 | __maybe_unused u64 spin_tbl_addr = (u64)get_spin_tbl_addr(); | |
26 | fdt32_t *reg; | |
27 | int addr_cells; | |
60385d94 | 28 | u64 val, core_id; |
40f8dec5 YS |
29 | size_t *boot_code_size = &(__secondary_boot_code_size); |
30 | ||
31 | off = fdt_path_offset(blob, "/cpus"); | |
32 | if (off < 0) { | |
33 | puts("couldn't find /cpus node\n"); | |
34 | return; | |
35 | } | |
36 | of_bus_default_count_cells(blob, off, &addr_cells, NULL); | |
37 | ||
38 | off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); | |
39 | while (off != -FDT_ERR_NOTFOUND) { | |
40 | reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0); | |
41 | if (reg) { | |
6a00a9cb | 42 | core_id = of_read_number(reg, addr_cells); |
60385d94 AB |
43 | if (core_id == 0 || (is_core_online(core_id))) { |
44 | val = spin_tbl_addr; | |
45 | val += id_to_core(core_id) * | |
46 | SPIN_TABLE_ELEM_SIZE; | |
47 | val = cpu_to_fdt64(val); | |
48 | fdt_setprop_string(blob, off, "enable-method", | |
49 | "spin-table"); | |
50 | fdt_setprop(blob, off, "cpu-release-addr", | |
51 | &val, sizeof(val)); | |
52 | } else { | |
53 | debug("skipping offline core\n"); | |
54 | } | |
40f8dec5 YS |
55 | } else { |
56 | puts("Warning: found cpu node without reg property\n"); | |
57 | } | |
58 | off = fdt_node_offset_by_prop_value(blob, off, "device_type", | |
59 | "cpu", 4); | |
60 | } | |
61 | ||
62 | fdt_add_mem_rsv(blob, (uintptr_t)&secondary_boot_code, | |
63 | *boot_code_size); | |
64 | } | |
65 | #endif | |
66 | ||
70e52d21 SY |
67 | /* |
68 | * the burden is on the the caller to not request a count | |
69 | * exceeding the bounds of the stream_ids[] array | |
70 | */ | |
71 | void alloc_stream_ids(int start_id, int count, u32 *stream_ids, int max_cnt) | |
72 | { | |
73 | int i; | |
74 | ||
75 | if (count > max_cnt) { | |
76 | printf("\n%s: ERROR: max per-device stream ID count exceed\n", | |
77 | __func__); | |
78 | return; | |
79 | } | |
80 | ||
81 | for (i = 0; i < count; i++) | |
82 | stream_ids[i] = start_id++; | |
83 | } | |
84 | ||
85 | /* | |
86 | * This function updates the mmu-masters property on the SMMU | |
87 | * node as per the SMMU binding-- phandle and list of stream IDs | |
88 | * for each MMU master. | |
89 | */ | |
90 | void append_mmu_masters(void *blob, const char *smmu_path, | |
91 | const char *master_name, u32 *stream_ids, int count) | |
92 | { | |
93 | u32 phandle; | |
94 | int smmu_nodeoffset; | |
95 | int master_nodeoffset; | |
96 | int i; | |
97 | ||
98 | /* get phandle of mmu master device */ | |
99 | master_nodeoffset = fdt_path_offset(blob, master_name); | |
100 | if (master_nodeoffset < 0) { | |
101 | printf("\n%s: ERROR: master not found\n", __func__); | |
102 | return; | |
103 | } | |
104 | phandle = fdt_get_phandle(blob, master_nodeoffset); | |
105 | if (!phandle) { /* if master has no phandle, create one */ | |
106 | phandle = fdt_create_phandle(blob, master_nodeoffset); | |
107 | if (!phandle) { | |
108 | printf("\n%s: ERROR: unable to create phandle\n", | |
109 | __func__); | |
110 | return; | |
111 | } | |
112 | } | |
113 | ||
114 | /* append it to mmu-masters */ | |
115 | smmu_nodeoffset = fdt_path_offset(blob, smmu_path); | |
116 | if (fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters", | |
117 | phandle) < 0) { | |
118 | printf("\n%s: ERROR: unable to update SMMU node\n", __func__); | |
119 | return; | |
120 | } | |
121 | ||
122 | /* for each stream ID, append to mmu-masters */ | |
123 | for (i = 0; i < count; i++) { | |
124 | fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters", | |
125 | stream_ids[i]); | |
126 | } | |
127 | ||
128 | /* fix up #stream-id-cells with stream ID count */ | |
129 | if (fdt_setprop_u32(blob, master_nodeoffset, "#stream-id-cells", | |
130 | count) < 0) | |
131 | printf("\n%s: ERROR: unable to update #stream-id-cells\n", | |
132 | __func__); | |
133 | } | |
134 | ||
135 | ||
136 | /* | |
137 | * The info below summarizes how streamID partitioning works | |
138 | * for ls2085a and how it is conveyed to the OS via the device tree. | |
139 | * | |
140 | * -non-PCI legacy, platform devices (USB, SD/MMC, SATA, DMA) | |
141 | * -all legacy devices get a unique ICID assigned and programmed in | |
142 | * their AMQR registers by u-boot | |
143 | * -u-boot updates the hardware device tree with streamID properties | |
144 | * for each platform/legacy device (smmu-masters property) | |
145 | * | |
146 | * -PCIe | |
147 | * -for each PCI controller that is active (as per RCW settings), | |
148 | * u-boot will allocate a range of ICID and convey that to Linux via | |
149 | * the device tree (smmu-masters property) | |
150 | * | |
151 | * -DPAA2 | |
152 | * -u-boot will allocate a range of ICIDs to be used by the Management | |
153 | * Complex for containers and will set these values in the MC DPC image. | |
154 | * -the MC is responsible for allocating and setting up ICIDs | |
155 | * for all DPAA2 devices. | |
156 | * | |
157 | */ | |
9f3183d2 | 158 | #ifdef CONFIG_FSL_LSCH3 |
70e52d21 SY |
159 | static void fdt_fixup_smmu(void *blob) |
160 | { | |
161 | int nodeoffset; | |
162 | ||
163 | nodeoffset = fdt_path_offset(blob, "/iommu@5000000"); | |
164 | if (nodeoffset < 0) { | |
165 | printf("\n%s: WARNING: no SMMU node found\n", __func__); | |
166 | return; | |
167 | } | |
168 | ||
169 | /* fixup for all PCI controllers */ | |
170 | #ifdef CONFIG_PCI | |
171 | fdt_fixup_smmu_pcie(blob); | |
172 | #endif | |
173 | } | |
9f3183d2 | 174 | #endif |
70e52d21 | 175 | |
40f8dec5 YS |
176 | void ft_cpu_setup(void *blob, bd_t *bd) |
177 | { | |
178 | #ifdef CONFIG_MP | |
179 | ft_fixup_cpu(blob); | |
180 | #endif | |
912cc40f BS |
181 | |
182 | #ifdef CONFIG_SYS_NS16550 | |
1e52835a | 183 | do_fixup_by_compat_u32(blob, "fsl,ns16550", |
912cc40f BS |
184 | "clock-frequency", CONFIG_SYS_NS16550_CLK, 1); |
185 | #endif | |
8b06460e | 186 | |
5be3b44c PK |
187 | #ifdef CONFIG_PCI |
188 | ft_pci_setup(blob, bd); | |
189 | #endif | |
190 | ||
9f3183d2 | 191 | #ifdef CONFIG_FSL_ESDHC |
8b06460e YL |
192 | fdt_fixup_esdhc(blob, bd); |
193 | #endif | |
70e52d21 | 194 | |
9f3183d2 | 195 | #ifdef CONFIG_FSL_LSCH3 |
70e52d21 | 196 | fdt_fixup_smmu(blob); |
9f3183d2 | 197 | #endif |
40f8dec5 | 198 | } |