]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
1aad38f6 DA |
2 | /* |
3 | * Copyright 2016 Texas Instruments, Inc. | |
1aad38f6 DA |
4 | */ |
5 | ||
6 | #include <common.h> | |
b08c8c48 | 7 | #include <linux/libfdt.h> |
1aad38f6 DA |
8 | #include <fdt_support.h> |
9 | #include <malloc.h> | |
10 | ||
11 | #include <asm/omap_common.h> | |
12 | #include <asm/arch-omap5/sys_proto.h> | |
13 | ||
14 | #ifdef CONFIG_TI_SECURE_DEVICE | |
15 | ||
16 | /* Give zero values if not already defined */ | |
17 | #ifndef TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ | |
18 | #define TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ (0) | |
19 | #endif | |
20 | #ifndef CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ | |
21 | #define CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ (0) | |
22 | #endif | |
23 | ||
24 | static u32 hs_irq_skip[] = { | |
25 | 8, /* Secure violation reporting interrupt */ | |
26 | 15, /* One interrupt for SDMA by secure world */ | |
27 | 118 /* One interrupt for Crypto DMA by secure world */ | |
28 | }; | |
29 | ||
30 | static int ft_hs_fixup_crossbar(void *fdt, bd_t *bd) | |
31 | { | |
32 | const char *path; | |
33 | int offs; | |
34 | int ret; | |
35 | int len, i, old_cnt, new_cnt; | |
36 | u32 *temp; | |
37 | const u32 *p_data; | |
38 | ||
39 | /* | |
40 | * Increase the size of the fdt | |
41 | * so we have some breathing room | |
42 | */ | |
43 | ret = fdt_increase_size(fdt, 512); | |
44 | if (ret < 0) { | |
45 | printf("Could not increase size of device tree: %s\n", | |
46 | fdt_strerror(ret)); | |
47 | return ret; | |
48 | } | |
49 | ||
50 | /* Reserve IRQs that are used/needed by secure world */ | |
51 | path = "/ocp/crossbar"; | |
52 | offs = fdt_path_offset(fdt, path); | |
53 | if (offs < 0) { | |
54 | debug("Node %s not found.\n", path); | |
55 | return 0; | |
56 | } | |
57 | ||
58 | /* Get current entries */ | |
59 | p_data = fdt_getprop(fdt, offs, "ti,irqs-skip", &len); | |
60 | if (p_data) | |
61 | old_cnt = len / sizeof(u32); | |
62 | else | |
63 | old_cnt = 0; | |
64 | ||
65 | new_cnt = sizeof(hs_irq_skip) / | |
66 | sizeof(hs_irq_skip[0]); | |
67 | ||
68 | /* Create new/updated skip list for HS parts */ | |
69 | temp = malloc(sizeof(u32) * (old_cnt + new_cnt)); | |
70 | for (i = 0; i < new_cnt; i++) | |
71 | temp[i] = cpu_to_fdt32(hs_irq_skip[i]); | |
72 | for (i = 0; i < old_cnt; i++) | |
73 | temp[i + new_cnt] = p_data[i]; | |
74 | ||
75 | /* Blow away old data and set new data */ | |
76 | fdt_delprop(fdt, offs, "ti,irqs-skip"); | |
77 | ret = fdt_setprop(fdt, offs, "ti,irqs-skip", | |
78 | temp, | |
79 | (old_cnt + new_cnt) * sizeof(u32)); | |
80 | free(temp); | |
81 | ||
82 | /* Check if the update worked */ | |
83 | if (ret < 0) { | |
84 | printf("Could not add ti,irqs-skip property to node %s: %s\n", | |
85 | path, fdt_strerror(ret)); | |
86 | return ret; | |
87 | } | |
88 | ||
89 | return 0; | |
90 | } | |
91 | ||
1aad38f6 DA |
92 | #if ((TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ != 0) || \ |
93 | (CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ != 0)) | |
94 | static int ft_hs_fixup_sram(void *fdt, bd_t *bd) | |
95 | { | |
96 | const char *path; | |
97 | int offs; | |
98 | int ret; | |
99 | u32 temp[2]; | |
100 | ||
101 | /* | |
102 | * Update SRAM reservations on secure devices. The OCMC RAM | |
103 | * is always reserved for secure use from the start of that | |
104 | * memory region | |
105 | */ | |
106 | path = "/ocp/ocmcram@40300000/sram-hs"; | |
107 | offs = fdt_path_offset(fdt, path); | |
108 | if (offs < 0) { | |
109 | debug("Node %s not found.\n", path); | |
110 | return 0; | |
111 | } | |
112 | ||
113 | /* relative start offset */ | |
114 | temp[0] = cpu_to_fdt32(0); | |
115 | /* reservation size */ | |
116 | temp[1] = cpu_to_fdt32(max(TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ, | |
117 | CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ)); | |
118 | fdt_delprop(fdt, offs, "reg"); | |
119 | ret = fdt_setprop(fdt, offs, "reg", temp, 2 * sizeof(u32)); | |
120 | if (ret < 0) { | |
121 | printf("Could not add reg property to node %s: %s\n", | |
122 | path, fdt_strerror(ret)); | |
123 | return ret; | |
124 | } | |
125 | ||
126 | return 0; | |
127 | } | |
128 | #else | |
129 | static int ft_hs_fixup_sram(void *fdt, bd_t *bd) { return 0; } | |
130 | #endif | |
131 | ||
132 | static void ft_hs_fixups(void *fdt, bd_t *bd) | |
133 | { | |
134 | /* Check we are running on an HS/EMU device type */ | |
135 | if (GP_DEVICE != get_device_type()) { | |
136 | if ((ft_hs_fixup_crossbar(fdt, bd) == 0) && | |
137 | (ft_hs_disable_rng(fdt, bd) == 0) && | |
66961394 | 138 | (ft_hs_fixup_sram(fdt, bd) == 0) && |
a8ff9685 AD |
139 | (ft_hs_fixup_dram(fdt, bd) == 0) && |
140 | (ft_hs_add_tee(fdt, bd) == 0)) | |
1aad38f6 DA |
141 | return; |
142 | } else { | |
143 | printf("ERROR: Incorrect device type (GP) detected!"); | |
144 | } | |
145 | /* Fixup failed or wrong device type */ | |
146 | hang(); | |
147 | } | |
148 | #else | |
149 | static void ft_hs_fixups(void *fdt, bd_t *bd) | |
150 | { | |
151 | } | |
66961394 | 152 | #endif /* #ifdef CONFIG_TI_SECURE_DEVICE */ |
1aad38f6 | 153 | |
1b42ab3e SA |
154 | #if defined(CONFIG_TARGET_DRA7XX_EVM) || defined(CONFIG_TARGET_AM57XX_EVM) |
155 | #define OPP_DSP_CLK_NUM 3 | |
156 | #define OPP_IVA_CLK_NUM 2 | |
157 | #define OPP_GPU_CLK_NUM 2 | |
158 | ||
159 | const char *dra7_opp_dsp_clk_names[OPP_DSP_CLK_NUM] = { | |
160 | "dpll_dsp_ck", | |
161 | "dpll_dsp_m2_ck", | |
162 | "dpll_dsp_m3x2_ck", | |
163 | }; | |
164 | ||
165 | const char *dra7_opp_iva_clk_names[OPP_IVA_CLK_NUM] = { | |
166 | "dpll_iva_ck", | |
167 | "dpll_iva_m2_ck", | |
168 | }; | |
169 | ||
170 | const char *dra7_opp_gpu_clk_names[OPP_GPU_CLK_NUM] = { | |
171 | "dpll_gpu_ck", | |
172 | "dpll_gpu_m2_ck", | |
173 | }; | |
174 | ||
175 | /* DSPEVE voltage domain */ | |
176 | u32 dra7_opp_dsp_clk_rates[NUM_OPPS][OPP_DSP_CLK_NUM] = { | |
177 | {}, /*OPP_LOW */ | |
178 | {600000000, 600000000, 400000000}, /* OPP_NOM */ | |
179 | {700000000, 700000000, 466666667}, /* OPP_OD */ | |
180 | {750000000, 750000000, 500000000}, /* OPP_HIGH */ | |
181 | }; | |
182 | ||
183 | /* IVA voltage domain */ | |
184 | u32 dra7_opp_iva_clk_rates[NUM_OPPS][OPP_IVA_CLK_NUM] = { | |
185 | {}, /* OPP_LOW */ | |
186 | {1165000000, 388333334}, /* OPP_NOM */ | |
187 | {860000000, 430000000}, /* OPP_OD */ | |
188 | {1064000000, 532000000}, /* OPP_HIGH */ | |
189 | }; | |
190 | ||
191 | /* GPU voltage domain */ | |
192 | u32 dra7_opp_gpu_clk_rates[NUM_OPPS][OPP_GPU_CLK_NUM] = { | |
193 | {}, /* OPP_LOW */ | |
194 | {1277000000, 425666667}, /* OPP_NOM */ | |
195 | {1000000000, 500000000}, /* OPP_OD */ | |
196 | {1064000000, 532000000}, /* OPP_HIGH */ | |
197 | }; | |
198 | ||
199 | static int ft_fixup_clocks(void *fdt, const char **names, u32 *rates, int num) | |
200 | { | |
201 | int offs, node_offs, ret, i; | |
202 | uint32_t phandle; | |
203 | ||
204 | offs = fdt_path_offset(fdt, "/ocp/l4@4a000000/cm_core_aon@5000/clocks"); | |
205 | if (offs < 0) { | |
206 | debug("Could not find cm_core_aon clocks node path offset : %s\n", | |
207 | fdt_strerror(offs)); | |
208 | return offs; | |
209 | } | |
210 | ||
211 | for (i = 0; i < num; i++) { | |
212 | node_offs = fdt_subnode_offset(fdt, offs, names[i]); | |
213 | if (node_offs < 0) { | |
214 | debug("Could not find clock sub-node %s: %s\n", | |
215 | names[i], fdt_strerror(node_offs)); | |
216 | return offs; | |
217 | } | |
218 | ||
219 | phandle = fdt_get_phandle(fdt, node_offs); | |
220 | if (!phandle) { | |
221 | debug("Could not find phandle for clock %s\n", | |
222 | names[i]); | |
223 | return -1; | |
224 | } | |
225 | ||
226 | ret = fdt_setprop_u32(fdt, node_offs, "assigned-clocks", | |
227 | phandle); | |
228 | if (ret < 0) { | |
229 | debug("Could not add assigned-clocks property to clock node %s: %s\n", | |
230 | names[i], fdt_strerror(ret)); | |
231 | return ret; | |
232 | } | |
233 | ||
234 | ret = fdt_setprop_u32(fdt, node_offs, "assigned-clock-rates", | |
235 | rates[i]); | |
236 | if (ret < 0) { | |
237 | debug("Could not add assigned-clock-rates property to clock node %s: %s\n", | |
238 | names[i], fdt_strerror(ret)); | |
239 | return ret; | |
240 | } | |
241 | } | |
242 | ||
243 | return 0; | |
244 | } | |
245 | ||
246 | static void ft_opp_clock_fixups(void *fdt, bd_t *bd) | |
247 | { | |
248 | const char **clk_names; | |
249 | u32 *clk_rates; | |
250 | int ret; | |
251 | ||
252 | if (!is_dra72x() && !is_dra7xx()) | |
253 | return; | |
254 | ||
255 | /* fixup DSP clocks */ | |
256 | clk_names = dra7_opp_dsp_clk_names; | |
257 | clk_rates = dra7_opp_dsp_clk_rates[get_voltrail_opp(VOLT_EVE)]; | |
258 | ret = ft_fixup_clocks(fdt, clk_names, clk_rates, OPP_DSP_CLK_NUM); | |
259 | if (ret) { | |
260 | printf("ft_fixup_clocks failed for DSP voltage domain: %s\n", | |
261 | fdt_strerror(ret)); | |
262 | return; | |
263 | } | |
264 | ||
265 | /* fixup IVA clocks */ | |
266 | clk_names = dra7_opp_iva_clk_names; | |
267 | clk_rates = dra7_opp_iva_clk_rates[get_voltrail_opp(VOLT_IVA)]; | |
268 | ret = ft_fixup_clocks(fdt, clk_names, clk_rates, OPP_IVA_CLK_NUM); | |
269 | if (ret) { | |
270 | printf("ft_fixup_clocks failed for IVA voltage domain: %s\n", | |
271 | fdt_strerror(ret)); | |
272 | return; | |
273 | } | |
274 | ||
275 | /* fixup GPU clocks */ | |
276 | clk_names = dra7_opp_gpu_clk_names; | |
277 | clk_rates = dra7_opp_gpu_clk_rates[get_voltrail_opp(VOLT_GPU)]; | |
278 | ret = ft_fixup_clocks(fdt, clk_names, clk_rates, OPP_GPU_CLK_NUM); | |
279 | if (ret) { | |
280 | printf("ft_fixup_clocks failed for GPU voltage domain: %s\n", | |
281 | fdt_strerror(ret)); | |
282 | return; | |
283 | } | |
284 | } | |
285 | #else | |
286 | static void ft_opp_clock_fixups(void *fdt, bd_t *bd) { } | |
287 | #endif /* CONFIG_TARGET_DRA7XX_EVM || CONFIG_TARGET_AM57XX_EVM */ | |
288 | ||
1aad38f6 DA |
289 | /* |
290 | * Place for general cpu/SoC FDT fixups. Board specific | |
291 | * fixups should remain in the board files which is where | |
292 | * this function should be called from. | |
293 | */ | |
294 | void ft_cpu_setup(void *fdt, bd_t *bd) | |
295 | { | |
296 | ft_hs_fixups(fdt, bd); | |
1b42ab3e | 297 | ft_opp_clock_fixups(fdt, bd); |
1aad38f6 | 298 | } |