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