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