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